blob: e248f56e21e64dae356b74a32538e18f80aeb08a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, 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),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700508 if (audio_extn_spkr_prot_is_enabled())
509 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700510 /* start usb playback thread */
511 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
512 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
513 audio_extn_usb_start_playback(adev);
514
515 /* start usb capture thread */
516 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
517 audio_extn_usb_start_capture(adev);
518
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800519 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
520 audio_extn_spkr_prot_is_enabled()) {
521 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700522 adev->snd_dev_ref_cnt[snd_device]--;
523 return -EINVAL;
524 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200525 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800526 if (audio_extn_spkr_prot_start_processing(snd_device)) {
527 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200528 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800529 return -EINVAL;
530 }
531 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700532 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700533 /* due to the possibility of calibration overwrite between listen
534 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700535 audio_extn_sound_trigger_update_device_status(snd_device,
536 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530537 audio_extn_listen_update_device_status(snd_device,
538 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700539 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700541 audio_extn_sound_trigger_update_device_status(snd_device,
542 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530543 audio_extn_listen_update_device_status(snd_device,
544 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700545 return -EINVAL;
546 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300547 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700548 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550 return 0;
551}
552
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700553int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700554 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700556 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
557
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800558 if (snd_device < SND_DEVICE_MIN ||
559 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800560 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800561 return -EINVAL;
562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
564 ALOGE("%s: device ref cnt is already 0", __func__);
565 return -EINVAL;
566 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700568 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700569
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700570 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
571 ALOGE("%s: Invalid sound device returned", __func__);
572 return -EINVAL;
573 }
574
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700576 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800577 /* exit usb play back thread */
578 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
579 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
580 audio_extn_usb_stop_playback();
581
582 /* exit usb capture thread */
583 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700584 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800585
586 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
587 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700588 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300589 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700590 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300591 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700592
Ashish Jain81eb2a82015-05-13 10:52:34 +0530593 if (snd_device == SND_DEVICE_OUT_HDMI)
594 adev->is_channel_status_set = false;
595
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200596 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700597 audio_extn_sound_trigger_update_device_status(snd_device,
598 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530599 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800600 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 return 0;
604}
605
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606static void check_usecases_codec_backend(struct audio_device *adev,
607 struct audio_usecase *uc_info,
608 snd_device_t snd_device)
609{
610 struct listnode *node;
611 struct audio_usecase *usecase;
612 bool switch_device[AUDIO_USECASE_MAX];
613 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800614 int backend_idx = DEFAULT_CODEC_BACKEND;
615 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616
617 /*
618 * This function is to make sure that all the usecases that are active on
619 * the hardware codec backend are always routed to any one device that is
620 * handled by the hardware codec.
621 * For example, if low-latency and deep-buffer usecases are currently active
622 * on speaker and out_set_parameters(headset) is received on low-latency
623 * output, then we have to make sure deep-buffer is also switched to headset,
624 * because of the limitation that both the devices cannot be enabled
625 * at the same time as they share the same backend.
626 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700627 /*
628 * This call is to check if we need to force routing for a particular stream
629 * If there is a backend configuration change for the device when a
630 * new stream starts, then ADM needs to be closed and re-opened with the new
631 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800632 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700633 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800634 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
635 snd_device);
636 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800638 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800639 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640 for (i = 0; i < AUDIO_USECASE_MAX; i++)
641 switch_device[i] = false;
642
643 list_for_each(node, &adev->usecase_list) {
644 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800645
646 if (usecase == uc_info)
647 continue;
648 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
649 ALOGV("%s: backend_idx: %d,"
650 "usecase_backend_idx: %d, curr device: %s, usecase device:"
651 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530652 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800654 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700655 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800656 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
657 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530658 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800659 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700660 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 switch_device[usecase->id] = true;
663 num_uc_to_switch++;
664 }
665 }
666
667 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700668 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530670 /* Make sure the previous devices to be disabled first and then enable the
671 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 list_for_each(node, &adev->usecase_list) {
673 usecase = node_to_item(node, struct audio_usecase, list);
674 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700675 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676 }
677 }
678
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700679 list_for_each(node, &adev->usecase_list) {
680 usecase = node_to_item(node, struct audio_usecase, list);
681 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700682 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700683 }
684 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 /* Re-route all the usecases on the shared backend other than the
687 specified usecase to new snd devices */
688 list_for_each(node, &adev->usecase_list) {
689 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530690 /* Update the out_snd_device only for the usecases that are enabled here */
691 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
692 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530693 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 }
695 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 }
697}
698
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700699static void check_and_route_capture_usecases(struct audio_device *adev,
700 struct audio_usecase *uc_info,
701 snd_device_t snd_device)
702{
703 struct listnode *node;
704 struct audio_usecase *usecase;
705 bool switch_device[AUDIO_USECASE_MAX];
706 int i, num_uc_to_switch = 0;
707
708 /*
709 * This function is to make sure that all the active capture usecases
710 * are always routed to the same input sound device.
711 * For example, if audio-record and voice-call usecases are currently
712 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
713 * is received for voice call then we have to make sure that audio-record
714 * usecase is also switched to earpiece i.e. voice-dmic-ef,
715 * because of the limitation that two devices cannot be enabled
716 * at the same time if they share the same backend.
717 */
718 for (i = 0; i < AUDIO_USECASE_MAX; i++)
719 switch_device[i] = false;
720
721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800723 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700725 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700726 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
727 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700728 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
730 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700731 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 switch_device[usecase->id] = true;
734 num_uc_to_switch++;
735 }
736 }
737
738 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700739 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700740
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530741 /* Make sure the previous devices to be disabled first and then enable the
742 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743 list_for_each(node, &adev->usecase_list) {
744 usecase = node_to_item(node, struct audio_usecase, list);
745 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700746 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800747 }
748 }
749
750 list_for_each(node, &adev->usecase_list) {
751 usecase = node_to_item(node, struct audio_usecase, list);
752 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700753 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 }
755 }
756
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700757 /* Re-route all the usecases on the shared backend other than the
758 specified usecase to new snd devices */
759 list_for_each(node, &adev->usecase_list) {
760 usecase = node_to_item(node, struct audio_usecase, list);
761 /* Update the in_snd_device only before enabling the audio route */
762 if (switch_device[usecase->id] ) {
763 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800764 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530765 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 }
767 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700768 }
769}
770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700772static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700774 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700775 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776
777 switch (channels) {
778 /*
779 * Do not handle stereo output in Multi-channel cases
780 * Stereo case is handled in normal playback path
781 */
782 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700783 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 break;
790 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700791 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800798 break;
799 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700800 ALOGE("HDMI does not support multi channel playback");
801 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800802 break;
803 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700804 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805}
806
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800807audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
808 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700809{
810 struct audio_usecase *usecase;
811 struct listnode *node;
812
813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800815 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700816 ALOGV("%s: usecase id %d", __func__, usecase->id);
817 return usecase->id;
818 }
819 }
820 return USECASE_INVALID;
821}
822
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700823struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700824 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825{
826 struct audio_usecase *usecase;
827 struct listnode *node;
828
829 list_for_each(node, &adev->usecase_list) {
830 usecase = node_to_item(node, struct audio_usecase, list);
831 if (usecase->id == uc_id)
832 return usecase;
833 }
834 return NULL;
835}
836
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700837int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800838{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800839 snd_device_t out_snd_device = SND_DEVICE_NONE;
840 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 struct audio_usecase *usecase = NULL;
842 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800843 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800844 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800845 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800846 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 usecase = get_usecase_from_list(adev, uc_id);
850 if (usecase == NULL) {
851 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
852 return -EINVAL;
853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800855 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800856 (usecase->type == VOIP_CALL) ||
857 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700858 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800859 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700860 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 usecase->devices = usecase->stream.out->devices;
862 } else {
863 /*
864 * If the voice call is active, use the sound devices of voice call usecase
865 * so that it would not result any device switch. All the usecases will
866 * be switched to new device when select_devices() is called for voice call
867 * usecase. This is to avoid switching devices for voice call when
868 * check_usecases_codec_backend() is called below.
869 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700870 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700871 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800872 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700873 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
874 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 in_snd_device = vc_usecase->in_snd_device;
876 out_snd_device = vc_usecase->out_snd_device;
877 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800878 } else if (voice_extn_compress_voip_is_active(adev)) {
879 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700880 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530881 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700882 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800883 in_snd_device = voip_usecase->in_snd_device;
884 out_snd_device = voip_usecase->out_snd_device;
885 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800886 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800887 hfp_ucid = audio_extn_hfp_get_usecase();
888 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700889 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800890 in_snd_device = hfp_usecase->in_snd_device;
891 out_snd_device = hfp_usecase->out_snd_device;
892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 if (usecase->type == PCM_PLAYBACK) {
895 usecase->devices = usecase->stream.out->devices;
896 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700898 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800899 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 if (usecase->stream.out == adev->primary_output &&
901 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800902 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 select_devices(adev, adev->active_input->usecase);
904 }
905 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 } else if (usecase->type == PCM_CAPTURE) {
907 usecase->devices = usecase->stream.in->device;
908 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700910 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530911 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
912 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
913 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
914 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700915 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700916 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700917 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
918 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700919 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700921 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 }
923 }
924
925 if (out_snd_device == usecase->out_snd_device &&
926 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927 return 0;
928 }
929
sangwoobc677242013-08-08 16:53:43 +0900930 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700931 out_snd_device, platform_get_snd_device_name(out_snd_device),
932 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800934 /*
935 * Limitation: While in call, to do a device switch we need to disable
936 * and enable both RX and TX devices though one of them is same as current
937 * device.
938 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700939 if ((usecase->type == VOICE_CALL) &&
940 (usecase->in_snd_device != SND_DEVICE_NONE) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700942 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700943 }
944
945 if (((usecase->type == VOICE_CALL) ||
946 (usecase->type == VOIP_CALL)) &&
947 (usecase->out_snd_device != SND_DEVICE_NONE)) {
948 /* Disable sidetone only if voice/voip call already exists */
949 if (voice_is_call_state_active(adev) ||
950 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700951 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800952 }
953
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 /* Disable current sound devices */
955 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700956 disable_audio_route(adev, usecase);
957 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700961 disable_audio_route(adev, usecase);
962 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 }
964
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800965 /* Applicable only on the targets that has external modem.
966 * New device information should be sent to modem before enabling
967 * the devices to reduce in-call device switch time.
968 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700969 if ((usecase->type == VOICE_CALL) &&
970 (usecase->in_snd_device != SND_DEVICE_NONE) &&
971 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800972 status = platform_switch_voice_call_enable_device_config(adev->platform,
973 out_snd_device,
974 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700975 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800976
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 /* Enable new sound devices */
978 if (out_snd_device != SND_DEVICE_NONE) {
979 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
980 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700981 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982 }
983
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700984 if (in_snd_device != SND_DEVICE_NONE) {
985 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700986 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988
Avinash Vaish71a8b972014-07-24 15:36:33 +0530989 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700990 status = platform_switch_voice_call_device_post(adev->platform,
991 out_snd_device,
992 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530993 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700994 /* Enable sidetone only if voice/voip call already exists */
995 if (voice_is_call_state_active(adev) ||
996 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700997 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530998 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800999
sangwoo170731f2013-06-08 15:36:36 +09001000 usecase->in_snd_device = in_snd_device;
1001 usecase->out_snd_device = out_snd_device;
1002
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301003 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001004 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301005 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001006 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301007 usecase->stream.out->flags,
1008 usecase->stream.out->format,
1009 usecase->stream.out->sample_rate,
1010 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301011 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301012 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001013 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301014 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001015
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001016 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001017
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001018 /* Applicable only on the targets that has external modem.
1019 * Enable device command should be sent to modem only after
1020 * enabling voice call mixer controls
1021 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001022 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001023 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1024 out_snd_device,
1025 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301026 ALOGD("%s: done",__func__);
1027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 return status;
1029}
1030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031static int stop_input_stream(struct stream_in *in)
1032{
1033 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 struct audio_usecase *uc_info;
1035 struct audio_device *adev = in->dev;
1036
Eric Laurentc8400632013-02-14 19:04:54 -08001037 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038
Eric Laurent994a6932013-07-17 11:51:42 -07001039 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 uc_info = get_usecase_from_list(adev, in->usecase);
1042 if (uc_info == NULL) {
1043 ALOGE("%s: Could not find the usecase (%d) in the list",
1044 __func__, in->usecase);
1045 return -EINVAL;
1046 }
1047
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001048 /* Close in-call recording streams */
1049 voice_check_and_stop_incall_rec_usecase(adev, in);
1050
Eric Laurent150dbfe2013-02-27 14:31:02 -08001051 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001052 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001053
1054 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001055 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001057 list_remove(&uc_info->list);
1058 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059
Eric Laurent994a6932013-07-17 11:51:42 -07001060 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 return ret;
1062}
1063
1064int start_input_stream(struct stream_in *in)
1065{
1066 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001067 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 struct audio_usecase *uc_info;
1069 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301070 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071
Mingming Yin2664a5b2015-09-03 10:53:11 -07001072 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1073 if (get_usecase_from_list(adev, usecase) == NULL)
1074 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301075 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1076 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001077
Naresh Tanniru80659832014-06-04 18:17:56 +05301078
1079 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301080 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301081 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301082 goto error_config;
1083 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301084
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001085 /* Check if source matches incall recording usecase criteria */
1086 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1087 if (ret)
1088 goto error_config;
1089 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001090 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1091
1092 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1093 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1094 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1095 goto error_config;
1096 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001097
Eric Laurentb23d5282013-05-14 15:27:20 -07001098 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 if (in->pcm_device_id < 0) {
1100 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1101 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001102 ret = -EINVAL;
1103 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105
1106 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001108
1109 if (!uc_info) {
1110 ret = -ENOMEM;
1111 goto error_config;
1112 }
1113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 uc_info->id = in->usecase;
1115 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001116 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 uc_info->devices = in->device;
1118 uc_info->in_snd_device = SND_DEVICE_NONE;
1119 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001121 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301122 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1123 adev->perf_lock_opts,
1124 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126
Eric Laurentc8400632013-02-14 19:04:54 -08001127 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001128 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1129
1130 unsigned int flags = PCM_IN;
1131 unsigned int pcm_open_retry_count = 0;
1132
1133 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1134 flags |= PCM_MMAP | PCM_NOIRQ;
1135 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1136 }
1137
1138 while (1) {
1139 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1140 flags, &in->config);
1141 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1142 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1143 if (in->pcm != NULL) {
1144 pcm_close(in->pcm);
1145 in->pcm = NULL;
1146 }
1147 if (pcm_open_retry_count-- == 0) {
1148 ret = -EIO;
1149 goto error_open;
1150 }
1151 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1152 continue;
1153 }
1154 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001156
1157 ALOGV("%s: pcm_prepare", __func__);
1158 ret = pcm_prepare(in->pcm);
1159 if (ret < 0) {
1160 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1161 pcm_close(in->pcm);
1162 in->pcm = NULL;
1163 goto error_open;
1164 }
1165
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301166 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001167 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001168
Eric Laurentc8400632013-02-14 19:04:54 -08001169 return ret;
1170
1171error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301172 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001174error_config:
1175 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301176 /*
1177 * sleep 50ms to allow sufficient time for kernel
1178 * drivers to recover incases like SSR.
1179 */
1180 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001182
1183 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001184}
1185
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001186void lock_input_stream(struct stream_in *in)
1187{
1188 pthread_mutex_lock(&in->pre_lock);
1189 pthread_mutex_lock(&in->lock);
1190 pthread_mutex_unlock(&in->pre_lock);
1191}
1192
1193void lock_output_stream(struct stream_out *out)
1194{
1195 pthread_mutex_lock(&out->pre_lock);
1196 pthread_mutex_lock(&out->lock);
1197 pthread_mutex_unlock(&out->pre_lock);
1198}
1199
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001200/* must be called with out->lock locked */
1201static int send_offload_cmd_l(struct stream_out* out, int command)
1202{
1203 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1204
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001205 if (!cmd) {
1206 ALOGE("failed to allocate mem for command 0x%x", command);
1207 return -ENOMEM;
1208 }
1209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001210 ALOGVV("%s %d", __func__, command);
1211
1212 cmd->cmd = command;
1213 list_add_tail(&out->offload_cmd_list, &cmd->node);
1214 pthread_cond_signal(&out->offload_cond);
1215 return 0;
1216}
1217
1218/* must be called iwth out->lock locked */
1219static void stop_compressed_output_l(struct stream_out *out)
1220{
1221 out->offload_state = OFFLOAD_STATE_IDLE;
1222 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001223 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001224 if (out->compr != NULL) {
1225 compress_stop(out->compr);
1226 while (out->offload_thread_blocked) {
1227 pthread_cond_wait(&out->cond, &out->lock);
1228 }
1229 }
1230}
1231
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001232bool is_offload_usecase(audio_usecase_t uc_id)
1233{
1234 unsigned int i;
1235 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1236 if (uc_id == offload_usecases[i])
1237 return true;
1238 }
1239 return false;
1240}
1241
vivek mehta446c3962015-09-14 10:57:35 -07001242static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001243{
vivek mehta446c3962015-09-14 10:57:35 -07001244 audio_usecase_t ret_uc = USECASE_INVALID;
1245 unsigned int offload_uc_index;
1246 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1247 if (!adev->multi_offload_enable) {
1248 if (is_direct_pcm)
1249 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1250 else
1251 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001252
vivek mehta446c3962015-09-14 10:57:35 -07001253 pthread_mutex_lock(&adev->lock);
1254 if (get_usecase_from_list(adev, ret_uc) != NULL)
1255 ret_uc = USECASE_INVALID;
1256 pthread_mutex_unlock(&adev->lock);
1257
1258 return ret_uc;
1259 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001260
1261 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001262 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1263 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1264 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1265 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001266 break;
1267 }
1268 }
vivek mehta446c3962015-09-14 10:57:35 -07001269
1270 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1271 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001272}
1273
1274static void free_offload_usecase(struct audio_device *adev,
1275 audio_usecase_t uc_id)
1276{
vivek mehta446c3962015-09-14 10:57:35 -07001277 unsigned int offload_uc_index;
1278 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1279
1280 if (!adev->multi_offload_enable)
1281 return;
1282
1283 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1284 if (offload_usecases[offload_uc_index] == uc_id) {
1285 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001286 break;
1287 }
1288 }
1289 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1290}
1291
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292static void *offload_thread_loop(void *context)
1293{
1294 struct stream_out *out = (struct stream_out *) context;
1295 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001296 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001297
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001298 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1299 set_sched_policy(0, SP_FOREGROUND);
1300 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1301
1302 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001303 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 for (;;) {
1305 struct offload_cmd *cmd = NULL;
1306 stream_callback_event_t event;
1307 bool send_callback = false;
1308
1309 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1310 __func__, list_empty(&out->offload_cmd_list),
1311 out->offload_state);
1312 if (list_empty(&out->offload_cmd_list)) {
1313 ALOGV("%s SLEEPING", __func__);
1314 pthread_cond_wait(&out->offload_cond, &out->lock);
1315 ALOGV("%s RUNNING", __func__);
1316 continue;
1317 }
1318
1319 item = list_head(&out->offload_cmd_list);
1320 cmd = node_to_item(item, struct offload_cmd, node);
1321 list_remove(item);
1322
1323 ALOGVV("%s STATE %d CMD %d out->compr %p",
1324 __func__, out->offload_state, cmd->cmd, out->compr);
1325
1326 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1327 free(cmd);
1328 break;
1329 }
1330
1331 if (out->compr == NULL) {
1332 ALOGE("%s: Compress handle is NULL", __func__);
1333 pthread_cond_signal(&out->cond);
1334 continue;
1335 }
1336 out->offload_thread_blocked = true;
1337 pthread_mutex_unlock(&out->lock);
1338 send_callback = false;
1339 switch(cmd->cmd) {
1340 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001341 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001342 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001343 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001344 send_callback = true;
1345 event = STREAM_CBK_EVENT_WRITE_READY;
1346 break;
1347 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001348 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301349 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001350 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301351 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001352 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301353 if (ret < 0)
1354 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301355 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301356 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001357 compress_drain(out->compr);
1358 else
1359 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301360 if (ret != -ENETRESET) {
1361 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301362 pthread_mutex_lock(&out->lock);
1363 out->send_new_metadata = 1;
1364 out->send_next_track_params = true;
1365 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301366 event = STREAM_CBK_EVENT_DRAIN_READY;
1367 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1368 } else
1369 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001370 break;
1371 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001372 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001373 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001374 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001375 send_callback = true;
1376 event = STREAM_CBK_EVENT_DRAIN_READY;
1377 break;
1378 default:
1379 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1380 break;
1381 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001382 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001383 out->offload_thread_blocked = false;
1384 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001385 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001386 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001387 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001388 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001389 free(cmd);
1390 }
1391
1392 pthread_cond_signal(&out->cond);
1393 while (!list_empty(&out->offload_cmd_list)) {
1394 item = list_head(&out->offload_cmd_list);
1395 list_remove(item);
1396 free(node_to_item(item, struct offload_cmd, node));
1397 }
1398 pthread_mutex_unlock(&out->lock);
1399
1400 return NULL;
1401}
1402
1403static int create_offload_callback_thread(struct stream_out *out)
1404{
1405 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1406 list_init(&out->offload_cmd_list);
1407 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1408 offload_thread_loop, out);
1409 return 0;
1410}
1411
1412static int destroy_offload_callback_thread(struct stream_out *out)
1413{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001414 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001415 stop_compressed_output_l(out);
1416 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1417
1418 pthread_mutex_unlock(&out->lock);
1419 pthread_join(out->offload_thread, (void **) NULL);
1420 pthread_cond_destroy(&out->offload_cond);
1421
1422 return 0;
1423}
1424
Eric Laurent07eeafd2013-10-06 12:52:49 -07001425static bool allow_hdmi_channel_config(struct audio_device *adev)
1426{
1427 struct listnode *node;
1428 struct audio_usecase *usecase;
1429 bool ret = true;
1430
1431 list_for_each(node, &adev->usecase_list) {
1432 usecase = node_to_item(node, struct audio_usecase, list);
1433 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1434 /*
1435 * If voice call is already existing, do not proceed further to avoid
1436 * disabling/enabling both RX and TX devices, CSD calls, etc.
1437 * Once the voice call done, the HDMI channels can be configured to
1438 * max channels of remaining use cases.
1439 */
1440 if (usecase->id == USECASE_VOICE_CALL) {
1441 ALOGD("%s: voice call is active, no change in HDMI channels",
1442 __func__);
1443 ret = false;
1444 break;
1445 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1446 ALOGD("%s: multi channel playback is active, "
1447 "no change in HDMI channels", __func__);
1448 ret = false;
1449 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001450 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001451 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001452 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1453 ", no change in HDMI channels", __func__,
1454 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001455 ret = false;
1456 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001457 }
1458 }
1459 }
1460 return ret;
1461}
1462
1463static int check_and_set_hdmi_channels(struct audio_device *adev,
1464 unsigned int channels)
1465{
1466 struct listnode *node;
1467 struct audio_usecase *usecase;
1468
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001469 unsigned int supported_channels = platform_edid_get_max_channels(
1470 adev->platform);
1471 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001472 /* Check if change in HDMI channel config is allowed */
1473 if (!allow_hdmi_channel_config(adev))
1474 return 0;
1475
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001476 if (channels > supported_channels)
1477 channels = supported_channels;
1478
Eric Laurent07eeafd2013-10-06 12:52:49 -07001479 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001480 ALOGD("%s: Requested channels are same as current channels(%d)",
1481 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001482 return 0;
1483 }
1484
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001485 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001486 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001487 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001488 adev->cur_hdmi_channels = channels;
1489
1490 /*
1491 * Deroute all the playback streams routed to HDMI so that
1492 * the back end is deactivated. Note that backend will not
1493 * be deactivated if any one stream is connected to it.
1494 */
1495 list_for_each(node, &adev->usecase_list) {
1496 usecase = node_to_item(node, struct audio_usecase, list);
1497 if (usecase->type == PCM_PLAYBACK &&
1498 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001499 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001500 }
1501 }
1502
1503 /*
1504 * Enable all the streams disabled above. Now the HDMI backend
1505 * will be activated with new channel configuration
1506 */
1507 list_for_each(node, &adev->usecase_list) {
1508 usecase = node_to_item(node, struct audio_usecase, list);
1509 if (usecase->type == PCM_PLAYBACK &&
1510 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001511 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001512 }
1513 }
1514
1515 return 0;
1516}
1517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518static int stop_output_stream(struct stream_out *out)
1519{
1520 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521 struct audio_usecase *uc_info;
1522 struct audio_device *adev = out->dev;
1523
Eric Laurent994a6932013-07-17 11:51:42 -07001524 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 uc_info = get_usecase_from_list(adev, out->usecase);
1527 if (uc_info == NULL) {
1528 ALOGE("%s: Could not find the usecase (%d) in the list",
1529 __func__, out->usecase);
1530 return -EINVAL;
1531 }
1532
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001533 if (is_offload_usecase(out->usecase) &&
1534 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001535 if (adev->visualizer_stop_output != NULL)
1536 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001537
1538 audio_extn_dts_remove_state_notifier_node(out->usecase);
1539
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001540 if (adev->offload_effects_stop_output != NULL)
1541 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1542 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001543
Eric Laurent150dbfe2013-02-27 14:31:02 -08001544 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001545 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546
1547 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001548 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001550 list_remove(&uc_info->list);
1551 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001553 if (is_offload_usecase(out->usecase) &&
1554 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1555 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1556 ALOGV("Disable passthrough , reset mixer to pcm");
1557 /* NO_PASSTHROUGH */
1558 out->compr_config.codec->compr_passthr = 0;
1559 audio_extn_dolby_set_hdmi_config(adev, out);
1560 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1561 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001562 /* Must be called after removing the usecase from list */
1563 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1564 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1565
Eric Laurent994a6932013-07-17 11:51:42 -07001566 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 return ret;
1568}
1569
1570int start_output_stream(struct stream_out *out)
1571{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001573 int sink_channels = 0;
1574 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 struct audio_usecase *uc_info;
1576 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301577 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001579 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1580 ret = -EINVAL;
1581 goto error_config;
1582 }
1583
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301584 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1585 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1586 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301587
Naresh Tanniru80659832014-06-04 18:17:56 +05301588 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301589 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301590 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301591 goto error_config;
1592 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301593
Eric Laurentb23d5282013-05-14 15:27:20 -07001594 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 if (out->pcm_device_id < 0) {
1596 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1597 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001598 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001599 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 }
1601
1602 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001603
1604 if (!uc_info) {
1605 ret = -ENOMEM;
1606 goto error_config;
1607 }
1608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 uc_info->id = out->usecase;
1610 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001611 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001612 uc_info->devices = out->devices;
1613 uc_info->in_snd_device = SND_DEVICE_NONE;
1614 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001615 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001616 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001617 if (is_offload_usecase(out->usecase)) {
1618 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001619 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1620 }
1621 }
Mingming Yin9c041392014-05-01 15:37:31 -07001622 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1623 if (!strncmp("true", prop_value, 4)) {
1624 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001625 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1626 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001627 check_and_set_hdmi_channels(adev, sink_channels);
1628 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001629 if (is_offload_usecase(out->usecase)) {
1630 unsigned int ch_count = out->compr_config.codec->ch_in;
1631 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1632 /* backend channel config for passthrough stream is stereo */
1633 ch_count = 2;
1634 check_and_set_hdmi_channels(adev, ch_count);
1635 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001636 check_and_set_hdmi_channels(adev, out->config.channels);
1637 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001638 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001639 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001640 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301642 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1643 adev->perf_lock_opts,
1644 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001645 select_devices(adev, out->usecase);
1646
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001647 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1648 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001649 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001650 unsigned int flags = PCM_OUT;
1651 unsigned int pcm_open_retry_count = 0;
1652 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1653 flags |= PCM_MMAP | PCM_NOIRQ;
1654 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1655 } else
1656 flags |= PCM_MONOTONIC;
1657
1658 while (1) {
1659 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1660 flags, &out->config);
1661 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1662 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1663 if (out->pcm != NULL) {
1664 pcm_close(out->pcm);
1665 out->pcm = NULL;
1666 }
1667 if (pcm_open_retry_count-- == 0) {
1668 ret = -EIO;
1669 goto error_open;
1670 }
1671 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1672 continue;
1673 }
1674 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001676
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001677 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1678 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001679
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001680 ALOGV("%s: pcm_prepare", __func__);
1681 if (pcm_is_ready(out->pcm)) {
1682 ret = pcm_prepare(out->pcm);
1683 if (ret < 0) {
1684 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1685 pcm_close(out->pcm);
1686 out->pcm = NULL;
1687 goto error_open;
1688 }
1689 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001690 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001691 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1692 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001694 out->compr = compress_open(adev->snd_card,
1695 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 COMPRESS_IN, &out->compr_config);
1697 if (out->compr && !is_compress_ready(out->compr)) {
1698 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1699 compress_close(out->compr);
1700 out->compr = NULL;
1701 ret = -EIO;
1702 goto error_open;
1703 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301704 /* compress_open sends params of the track, so reset the flag here */
1705 out->is_compr_metadata_avail = false;
1706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 if (out->offload_callback)
1708 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001709
Fred Oh3f43e742015-03-04 18:42:34 -08001710 /* Since small bufs uses blocking writes, a write will be blocked
1711 for the default max poll time (20s) in the event of an SSR.
1712 Reduce the poll time to observe and deal with SSR faster.
1713 */
1714 if (out->use_small_bufs) {
1715 compress_set_max_poll_wait(out->compr, 1000);
1716 }
1717
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001718 audio_extn_dts_create_state_notifier_node(out->usecase);
1719 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1720 popcount(out->channel_mask),
1721 out->playback_started);
1722
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001723#ifdef DS1_DOLBY_DDP_ENABLED
1724 if (audio_extn_is_dolby_format(out->format))
1725 audio_extn_dolby_send_ddp_endp_params(adev);
1726#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001727 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1728 if (adev->visualizer_start_output != NULL)
1729 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1730 if (adev->offload_effects_start_output != NULL)
1731 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001732 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001733 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301735 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001736 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301740 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001742error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301743 /*
1744 * sleep 50ms to allow sufficient time for kernel
1745 * drivers to recover incases like SSR.
1746 */
1747 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001748 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749}
1750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751static int check_input_parameters(uint32_t sample_rate,
1752 audio_format_t format,
1753 int channel_count)
1754{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001755 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001757 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001758 !voice_extn_compress_voip_is_format_supported(format) &&
1759 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001760
1761 switch (channel_count) {
1762 case 1:
1763 case 2:
1764 case 6:
1765 break;
1766 default:
1767 ret = -EINVAL;
1768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
1770 switch (sample_rate) {
1771 case 8000:
1772 case 11025:
1773 case 12000:
1774 case 16000:
1775 case 22050:
1776 case 24000:
1777 case 32000:
1778 case 44100:
1779 case 48000:
1780 break;
1781 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001782 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 }
1784
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001785 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786}
1787
1788static size_t get_input_buffer_size(uint32_t sample_rate,
1789 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001790 int channel_count,
1791 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792{
1793 size_t size = 0;
1794
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001795 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1796 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001798 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001799 if (is_low_latency)
1800 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001801 /* ToDo: should use frame_size computed based on the format and
1802 channel_count here. */
1803 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001805 /* make sure the size is multiple of 32 bytes
1806 * At 48 kHz mono 16-bit PCM:
1807 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1808 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1809 */
1810 size += 0x1f;
1811 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001812
1813 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814}
1815
1816static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1817{
1818 struct stream_out *out = (struct stream_out *)stream;
1819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001820 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821}
1822
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001823static int out_set_sample_rate(struct audio_stream *stream __unused,
1824 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825{
1826 return -ENOSYS;
1827}
1828
1829static size_t out_get_buffer_size(const struct audio_stream *stream)
1830{
1831 struct stream_out *out = (struct stream_out *)stream;
1832
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001833 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001835 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1836 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001838 return out->config.period_size *
1839 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840}
1841
1842static uint32_t out_get_channels(const struct audio_stream *stream)
1843{
1844 struct stream_out *out = (struct stream_out *)stream;
1845
1846 return out->channel_mask;
1847}
1848
1849static audio_format_t out_get_format(const struct audio_stream *stream)
1850{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001851 struct stream_out *out = (struct stream_out *)stream;
1852
1853 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854}
1855
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001856static int out_set_format(struct audio_stream *stream __unused,
1857 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858{
1859 return -ENOSYS;
1860}
1861
1862static int out_standby(struct audio_stream *stream)
1863{
1864 struct stream_out *out = (struct stream_out *)stream;
1865 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001866
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301867 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1868 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001869 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1870 /* Ignore standby in case of voip call because the voip output
1871 * stream is closed in adev_close_output_stream()
1872 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301873 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001874 return 0;
1875 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001877 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001879 if (adev->adm_deregister_stream)
1880 adev->adm_deregister_stream(adev->adm_data, out->handle);
1881
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001882 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001884 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001885 if (out->pcm) {
1886 pcm_close(out->pcm);
1887 out->pcm = NULL;
1888 }
1889 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001890 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001891 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301892 out->send_next_track_params = false;
1893 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001894 out->gapless_mdata.encoder_delay = 0;
1895 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896 if (out->compr != NULL) {
1897 compress_close(out->compr);
1898 out->compr = NULL;
1899 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001900 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001902 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 }
1904 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001905 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 return 0;
1907}
1908
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001909static int out_dump(const struct audio_stream *stream __unused,
1910 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911{
1912 return 0;
1913}
1914
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001915static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1916{
1917 int ret = 0;
1918 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001919
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001920 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001921 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001922 return -EINVAL;
1923 }
1924
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301925 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001926
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001927 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1928 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301929 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001930 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1932 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301933 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934 }
1935
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936 ALOGV("%s new encoder delay %u and padding %u", __func__,
1937 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1938
1939 return 0;
1940}
1941
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001942static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1943{
1944 return out == adev->primary_output || out == adev->voice_tx_output;
1945}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1948{
1949 struct stream_out *out = (struct stream_out *)stream;
1950 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001951 struct audio_usecase *usecase;
1952 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 struct str_parms *parms;
1954 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001955 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001956 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957
sangwoobc677242013-08-08 16:53:43 +09001958 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001959 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301961 if (!parms)
1962 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001963 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1964 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001966 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001967 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001969 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301970 * When HDMI cable is unplugged/usb hs is disconnected the
1971 * music playback is paused and the policy manager sends routing=0
1972 * But the audioflingercontinues to write data until standby time
1973 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001974 * Avoid this by routing audio to speaker until standby.
1975 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301976 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1977 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001978 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001979 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1980 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 }
1982
1983 /*
1984 * select_devices() call below switches all the usecases on the same
1985 * backend to the new device. Refer to check_usecases_codec_backend() in
1986 * the select_devices(). But how do we undo this?
1987 *
1988 * For example, music playback is active on headset (deep-buffer usecase)
1989 * and if we go to ringtones and select a ringtone, low-latency usecase
1990 * will be started on headset+speaker. As we can't enable headset+speaker
1991 * and headset devices at the same time, select_devices() switches the music
1992 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1993 * So when the ringtone playback is completed, how do we undo the same?
1994 *
1995 * We are relying on the out_set_parameters() call on deep-buffer output,
1996 * once the ringtone playback is ended.
1997 * NOTE: We should not check if the current devices are same as new devices.
1998 * Because select_devices() must be called to switch back the music
1999 * playback to headset.
2000 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002001 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002002 out->devices = val;
2003
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302004 if (!out->standby) {
2005 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2006 adev->perf_lock_opts,
2007 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002008 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302009 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2010 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002011
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002012 if (output_drives_call(adev, out)) {
2013 if(!voice_is_in_call(adev)) {
2014 if (adev->mode == AUDIO_MODE_IN_CALL) {
2015 adev->current_call_output = out;
2016 ret = voice_start_call(adev);
2017 }
2018 } else {
2019 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002020 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002021 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002022 }
2023 }
2024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002026 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002028
2029 if (out == adev->primary_output) {
2030 pthread_mutex_lock(&adev->lock);
2031 audio_extn_set_parameters(adev, parms);
2032 pthread_mutex_unlock(&adev->lock);
2033 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002034 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002035 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002036 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002037
2038 audio_extn_dts_create_state_notifier_node(out->usecase);
2039 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2040 popcount(out->channel_mask),
2041 out->playback_started);
2042
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002043 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002044 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302047error:
Eric Laurent994a6932013-07-17 11:51:42 -07002048 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 return ret;
2050}
2051
2052static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2053{
2054 struct stream_out *out = (struct stream_out *)stream;
2055 struct str_parms *query = str_parms_create_str(keys);
2056 char *str;
2057 char value[256];
2058 struct str_parms *reply = str_parms_create();
2059 size_t i, j;
2060 int ret;
2061 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002062
2063 if (!query || !reply) {
2064 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2065 return NULL;
2066 }
2067
Eric Laurent994a6932013-07-17 11:51:42 -07002068 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2070 if (ret >= 0) {
2071 value[0] = '\0';
2072 i = 0;
2073 while (out->supported_channel_masks[i] != 0) {
2074 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2075 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2076 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002077 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002079 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 first = false;
2081 break;
2082 }
2083 }
2084 i++;
2085 }
2086 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2087 str = str_parms_to_str(reply);
2088 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002089 voice_extn_out_get_parameters(out, query, reply);
2090 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002091 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002092 free(str);
2093 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002096
Alexy Joseph62142aa2015-11-16 15:10:34 -08002097
2098 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2099 if (ret >= 0) {
2100 value[0] = '\0';
2101 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2102 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302103 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002104 } else {
2105 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302106 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002107 }
2108 str_parms_add_str(reply, "is_direct_pcm_track", value);
2109 str = str_parms_to_str(reply);
2110 }
2111
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002112 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2113 if (ret >= 0) {
2114 value[0] = '\0';
2115 i = 0;
2116 first = true;
2117 while (out->supported_formats[i] != 0) {
2118 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2119 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2120 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002121 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002122 }
2123 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2124 first = false;
2125 break;
2126 }
2127 }
2128 i++;
2129 }
2130 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2131 str = str_parms_to_str(reply);
2132 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 str_parms_destroy(query);
2134 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002135 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 return str;
2137}
2138
2139static uint32_t out_get_latency(const struct audio_stream_out *stream)
2140{
2141 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002142 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143
Alexy Josephaa54c872014-12-03 02:46:47 -08002144 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002145 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002146 } else {
2147 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002149 }
2150
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302151 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002152 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153}
2154
2155static int out_set_volume(struct audio_stream_out *stream, float left,
2156 float right)
2157{
Eric Laurenta9024de2013-04-04 09:19:12 -07002158 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 int volume[2];
2160
Eric Laurenta9024de2013-04-04 09:19:12 -07002161 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2162 /* only take left channel into account: the API is for stereo anyway */
2163 out->muted = (left == 0.0f);
2164 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002165 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002166 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2167 /*
2168 * Set mute or umute on HDMI passthrough stream.
2169 * Only take left channel into account.
2170 * Mute is 0 and unmute 1
2171 */
2172 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2173 } else {
2174 char mixer_ctl_name[128];
2175 struct audio_device *adev = out->dev;
2176 struct mixer_ctl *ctl;
2177 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002178 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002180 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2181 "Compress Playback %d Volume", pcm_device_id);
2182 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2183 if (!ctl) {
2184 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2185 __func__, mixer_ctl_name);
2186 return -EINVAL;
2187 }
2188 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2189 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2190 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2191 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002192 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002193 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 return -ENOSYS;
2196}
2197
2198static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2199 size_t bytes)
2200{
2201 struct stream_out *out = (struct stream_out *)stream;
2202 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302203 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002204 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002206 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302207
Naresh Tanniru80659832014-06-04 18:17:56 +05302208 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002209 // increase written size during SSR to avoid mismatch
2210 // with the written frames count in AF
2211 if (!is_offload_usecase(out->usecase))
2212 out->written += bytes / (out->config.channels * sizeof(short));
2213
Naresh Tanniru80659832014-06-04 18:17:56 +05302214 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302215 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302216 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302217 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002218 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302219 //during SSR for compress usecase we should return error to flinger
2220 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2221 pthread_mutex_unlock(&out->lock);
2222 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302223 }
2224 }
2225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002227 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002228 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002229 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2230 ret = voice_extn_compress_voip_start_output_stream(out);
2231 else
2232 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002233 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002236 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 goto exit;
2238 }
vivek mehta446c3962015-09-14 10:57:35 -07002239 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002240 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242
Ashish Jain81eb2a82015-05-13 10:52:34 +05302243 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2244 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2245 adev->is_channel_status_set = true;
2246 }
2247
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002248 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002249 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002250 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002251 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2253 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302254 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2255 ALOGD("copl(%p):send next track params in gapless", out);
2256 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2257 out->send_next_track_params = false;
2258 out->is_compr_metadata_avail = false;
2259 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002260 }
2261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302263 if (ret < 0)
2264 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002265 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002266 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302267 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302269 } else if (-ENETRESET == ret) {
2270 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2271 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2272 pthread_mutex_unlock(&out->lock);
2273 out_standby(&out->stream.common);
2274 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002275 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302276 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002277 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002278 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 out->playback_started = 1;
2280 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002281
2282 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2283 popcount(out->channel_mask),
2284 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002285 }
2286 pthread_mutex_unlock(&out->lock);
2287 return ret;
2288 } else {
2289 if (out->pcm) {
2290 if (out->muted)
2291 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002292
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002294
2295 if (adev->adm_request_focus)
2296 adev->adm_request_focus(adev->adm_data, out->handle);
2297
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002298 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2299 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2300 else
2301 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002302
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302303 if (ret < 0)
2304 ret = -errno;
2305 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002306 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002307
2308 if (adev->adm_abandon_focus)
2309 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311 }
2312
2313exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302314 /* ToDo: There may be a corner case when SSR happens back to back during
2315 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302316 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302317 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302318 }
2319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 pthread_mutex_unlock(&out->lock);
2321
2322 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002323 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002324 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302325 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302326 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302327 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302328 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302329 out->standby = true;
2330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002332 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302333 out_get_sample_rate(&out->stream.common));
2334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 }
2336 return bytes;
2337}
2338
2339static int out_get_render_position(const struct audio_stream_out *stream,
2340 uint32_t *dsp_frames)
2341{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302343 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002344
2345 if (dsp_frames == NULL)
2346 return -EINVAL;
2347
2348 *dsp_frames = 0;
2349 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002350 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002351 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302353 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302355 if (ret < 0)
2356 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 ALOGVV("%s rendered frames %d sample_rate %d",
2358 __func__, *dsp_frames, out->sample_rate);
2359 }
2360 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302361 if (-ENETRESET == ret) {
2362 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2363 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2364 return -EINVAL;
2365 } else if(ret < 0) {
2366 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2367 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302368 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2369 /*
2370 * Handle corner case where compress session is closed during SSR
2371 * and timestamp is queried
2372 */
2373 ALOGE(" ERROR: sound card not active, return error");
2374 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302375 } else {
2376 return 0;
2377 }
Zhou Song32a556e2015-05-05 10:46:56 +08002378 } else if (audio_is_linear_pcm(out->format)) {
2379 *dsp_frames = out->written;
2380 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 } else
2382 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383}
2384
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002385static int out_add_audio_effect(const struct audio_stream *stream __unused,
2386 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387{
2388 return 0;
2389}
2390
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002391static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2392 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393{
2394 return 0;
2395}
2396
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002397static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2398 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399{
2400 return -EINVAL;
2401}
2402
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002403static int out_get_presentation_position(const struct audio_stream_out *stream,
2404 uint64_t *frames, struct timespec *timestamp)
2405{
2406 struct stream_out *out = (struct stream_out *)stream;
2407 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002408 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002409
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002410 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002411
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002412 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002413 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302414 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002415 &out->sample_rate);
2416 ALOGVV("%s rendered frames %ld sample_rate %d",
2417 __func__, dsp_frames, out->sample_rate);
2418 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302419 if (ret < 0)
2420 ret = -errno;
2421 if (-ENETRESET == ret) {
2422 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2423 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2424 ret = -EINVAL;
2425 } else
2426 ret = 0;
2427
Eric Laurent949a0892013-09-20 09:20:13 -07002428 /* this is the best we can do */
2429 clock_gettime(CLOCK_MONOTONIC, timestamp);
2430 }
2431 } else {
2432 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002433 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002434 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2435 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002436 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002437 // This adjustment accounts for buffering after app processor.
2438 // It is based on estimated DSP latency per use case, rather than exact.
2439 signed_frames -=
2440 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2441
Eric Laurent949a0892013-09-20 09:20:13 -07002442 // It would be unusual for this value to be negative, but check just in case ...
2443 if (signed_frames >= 0) {
2444 *frames = signed_frames;
2445 ret = 0;
2446 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002447 }
2448 }
2449 }
2450
2451 pthread_mutex_unlock(&out->lock);
2452
2453 return ret;
2454}
2455
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456static int out_set_callback(struct audio_stream_out *stream,
2457 stream_callback_t callback, void *cookie)
2458{
2459 struct stream_out *out = (struct stream_out *)stream;
2460
2461 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002462 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 out->offload_callback = callback;
2464 out->offload_cookie = cookie;
2465 pthread_mutex_unlock(&out->lock);
2466 return 0;
2467}
2468
2469static int out_pause(struct audio_stream_out* stream)
2470{
2471 struct stream_out *out = (struct stream_out *)stream;
2472 int status = -ENOSYS;
2473 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002474 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002475 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002476 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002477 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302478 struct audio_device *adev = out->dev;
2479 int snd_scard_state = get_snd_card_state(adev);
2480
2481 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2482 status = compress_pause(out->compr);
2483
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002485
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302486 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002487 audio_extn_dts_notify_playback_state(out->usecase, 0,
2488 out->sample_rate, popcount(out->channel_mask),
2489 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 }
2491 pthread_mutex_unlock(&out->lock);
2492 }
2493 return status;
2494}
2495
2496static int out_resume(struct audio_stream_out* stream)
2497{
2498 struct stream_out *out = (struct stream_out *)stream;
2499 int status = -ENOSYS;
2500 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002501 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002502 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002504 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002505 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302506 struct audio_device *adev = out->dev;
2507 int snd_scard_state = get_snd_card_state(adev);
2508
2509 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2510 status = compress_resume(out->compr);
2511
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002512 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002513
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302514 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002515 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2516 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517 }
2518 pthread_mutex_unlock(&out->lock);
2519 }
2520 return status;
2521}
2522
2523static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 int status = -ENOSYS;
2527 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002528 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002529 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2531 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2532 else
2533 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2534 pthread_mutex_unlock(&out->lock);
2535 }
2536 return status;
2537}
2538
2539static int out_flush(struct audio_stream_out* stream)
2540{
2541 struct stream_out *out = (struct stream_out *)stream;
2542 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002543 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002544 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002545 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 stop_compressed_output_l(out);
2547 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002548 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002549 return 0;
2550 }
2551 return -ENOSYS;
2552}
2553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554/** audio_stream_in implementation **/
2555static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2556{
2557 struct stream_in *in = (struct stream_in *)stream;
2558
2559 return in->config.rate;
2560}
2561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002562static int in_set_sample_rate(struct audio_stream *stream __unused,
2563 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564{
2565 return -ENOSYS;
2566}
2567
2568static size_t in_get_buffer_size(const struct audio_stream *stream)
2569{
2570 struct stream_in *in = (struct stream_in *)stream;
2571
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002572 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2573 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002574 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2575 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002576
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002577 return in->config.period_size *
2578 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579}
2580
2581static uint32_t in_get_channels(const struct audio_stream *stream)
2582{
2583 struct stream_in *in = (struct stream_in *)stream;
2584
2585 return in->channel_mask;
2586}
2587
2588static audio_format_t in_get_format(const struct audio_stream *stream)
2589{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002590 struct stream_in *in = (struct stream_in *)stream;
2591
2592 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593}
2594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002595static int in_set_format(struct audio_stream *stream __unused,
2596 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597{
2598 return -ENOSYS;
2599}
2600
2601static int in_standby(struct audio_stream *stream)
2602{
2603 struct stream_in *in = (struct stream_in *)stream;
2604 struct audio_device *adev = in->dev;
2605 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302606 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2607 stream, in->usecase, use_case_table[in->usecase]);
2608
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002609 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2610 /* Ignore standby in case of voip call because the voip input
2611 * stream is closed in adev_close_input_stream()
2612 */
2613 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2614 return status;
2615 }
2616
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002617 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002618 if (!in->standby && in->is_st_session) {
2619 ALOGD("%s: sound trigger pcm stop lab", __func__);
2620 audio_extn_sound_trigger_stop_lab(in);
2621 in->standby = 1;
2622 }
2623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002625 if (adev->adm_deregister_stream)
2626 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2627
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002628 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002630 if (in->pcm) {
2631 pcm_close(in->pcm);
2632 in->pcm = NULL;
2633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002635 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 }
2637 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002638 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 return status;
2640}
2641
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002642static int in_dump(const struct audio_stream *stream __unused,
2643 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644{
2645 return 0;
2646}
2647
2648static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2649{
2650 struct stream_in *in = (struct stream_in *)stream;
2651 struct audio_device *adev = in->dev;
2652 struct str_parms *parms;
2653 char *str;
2654 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002655 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302657 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 parms = str_parms_create_str(kvpairs);
2659
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302660 if (!parms)
2661 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002662 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002663 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002664
2665 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2666 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 val = atoi(value);
2668 /* no audio source uses val == 0 */
2669 if ((in->source != val) && (val != 0)) {
2670 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002671 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2672 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2673 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2674 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002675 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002676 err = voice_extn_compress_voip_open_input_stream(in);
2677 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002678 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002679 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002680 }
2681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 }
2683 }
2684
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002685 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2686 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002688 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 in->device = val;
2690 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002691 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002692 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 }
2694 }
2695
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002696done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002698 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699
2700 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302701error:
Eric Laurent994a6932013-07-17 11:51:42 -07002702 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 return ret;
2704}
2705
2706static char* in_get_parameters(const struct audio_stream *stream,
2707 const char *keys)
2708{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002709 struct stream_in *in = (struct stream_in *)stream;
2710 struct str_parms *query = str_parms_create_str(keys);
2711 char *str;
2712 char value[256];
2713 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002714
2715 if (!query || !reply) {
2716 ALOGE("in_get_parameters: failed to create query or reply");
2717 return NULL;
2718 }
2719
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002720 ALOGV("%s: enter: keys - %s", __func__, keys);
2721
2722 voice_extn_in_get_parameters(in, query, reply);
2723
2724 str = str_parms_to_str(reply);
2725 str_parms_destroy(query);
2726 str_parms_destroy(reply);
2727
2728 ALOGV("%s: exit: returns - %s", __func__, str);
2729 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730}
2731
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002732static int in_set_gain(struct audio_stream_in *stream __unused,
2733 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
2735 return 0;
2736}
2737
2738static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2739 size_t bytes)
2740{
2741 struct stream_in *in = (struct stream_in *)stream;
2742 struct audio_device *adev = in->dev;
2743 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302744 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002746 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302747
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002748 if (in->is_st_session) {
2749 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2750 /* Read from sound trigger HAL */
2751 audio_extn_sound_trigger_read(in, buffer, bytes);
2752 pthread_mutex_unlock(&in->lock);
2753 return bytes;
2754 }
2755
2756 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2757 ALOGD(" %s: sound card is not active/SSR state", __func__);
2758 ret= -EIO;;
2759 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302760 }
2761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002763 pthread_mutex_lock(&adev->lock);
2764 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2765 ret = voice_extn_compress_voip_start_input_stream(in);
2766 else
2767 ret = start_input_stream(in);
2768 pthread_mutex_unlock(&adev->lock);
2769 if (ret != 0) {
2770 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 }
2772 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002773 if (adev->adm_register_input_stream)
2774 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002777 if (adev->adm_request_focus)
2778 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002781 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002782 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002783 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2784 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002785 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2786 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002787 else
2788 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302789 if (ret < 0)
2790 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 }
2792
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002793 if (adev->adm_abandon_focus)
2794 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 /*
2797 * Instead of writing zeroes here, we could trust the hardware
2798 * to always provide zeroes when muted.
2799 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302800 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2801 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 memset(buffer, 0, bytes);
2803
2804exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302805 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302806 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002807 if (-ENETRESET == ret)
2808 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 pthread_mutex_unlock(&in->lock);
2811
2812 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302813 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302814 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302815 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302816 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302817 in->standby = true;
2818 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302819 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002821 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002822 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302823 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 }
2825 return bytes;
2826}
2827
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002828static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829{
2830 return 0;
2831}
2832
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002833static int add_remove_audio_effect(const struct audio_stream *stream,
2834 effect_handle_t effect,
2835 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002837 struct stream_in *in = (struct stream_in *)stream;
2838 int status = 0;
2839 effect_descriptor_t desc;
2840
2841 status = (*effect)->get_descriptor(effect, &desc);
2842 if (status != 0)
2843 return status;
2844
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002845 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002846 pthread_mutex_lock(&in->dev->lock);
2847 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2848 in->enable_aec != enable &&
2849 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2850 in->enable_aec = enable;
2851 if (!in->standby)
2852 select_devices(in->dev, in->usecase);
2853 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002854 if (in->enable_ns != enable &&
2855 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2856 in->enable_ns = enable;
2857 if (!in->standby)
2858 select_devices(in->dev, in->usecase);
2859 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002860 pthread_mutex_unlock(&in->dev->lock);
2861 pthread_mutex_unlock(&in->lock);
2862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 return 0;
2864}
2865
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002866static int in_add_audio_effect(const struct audio_stream *stream,
2867 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868{
Eric Laurent994a6932013-07-17 11:51:42 -07002869 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002870 return add_remove_audio_effect(stream, effect, true);
2871}
2872
2873static int in_remove_audio_effect(const struct audio_stream *stream,
2874 effect_handle_t effect)
2875{
Eric Laurent994a6932013-07-17 11:51:42 -07002876 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002877 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878}
2879
2880static int adev_open_output_stream(struct audio_hw_device *dev,
2881 audio_io_handle_t handle,
2882 audio_devices_t devices,
2883 audio_output_flags_t flags,
2884 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002885 struct audio_stream_out **stream_out,
2886 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887{
2888 struct audio_device *adev = (struct audio_device *)dev;
2889 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002890 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002891 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302894
2895 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2896 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002897 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302898 return -EINVAL;
2899 }
2900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2902
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302903 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2904 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2905 devices, flags, &out->stream);
2906
2907
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002908 if (!out) {
2909 return -ENOMEM;
2910 }
2911
Haynes Mathew George204045b2015-02-25 20:32:03 -08002912 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002913 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002914 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 if (devices == AUDIO_DEVICE_NONE)
2917 devices = AUDIO_DEVICE_OUT_SPEAKER;
2918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 out->flags = flags;
2920 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002921 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002922 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002923 out->sample_rate = config->sample_rate;
2924 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2925 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002926 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002927 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002928 out->non_blocking = 0;
2929 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930
2931 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002932 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2933 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002934 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2935 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2936
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002937 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002938 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2939 ret = read_hdmi_channel_masks(out);
2940
2941 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2942 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002943 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002944 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002945 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002946
2947 if (config->sample_rate == 0)
2948 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2949 if (config->channel_mask == 0)
2950 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2951
2952 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2955 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002957 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002959 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2960 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002961 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002962 ret = voice_extn_compress_voip_open_output_stream(out);
2963 if (ret != 0) {
2964 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2965 __func__, ret);
2966 goto error_open;
2967 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002968 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2969 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2970
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2972 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2973 ALOGE("%s: Unsupported Offload information", __func__);
2974 ret = -EINVAL;
2975 goto error_open;
2976 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002977
2978 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2979 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2980 ALOGV("read and update_pass through formats");
2981 ret = audio_extn_dolby_update_passt_formats(adev, out);
2982 if(ret != 0) {
2983 goto error_open;
2984 }
2985 if(config->offload_info.format == 0)
2986 config->offload_info.format = out->supported_formats[0];
2987 }
2988
Mingming Yin90310102013-11-13 16:57:00 -08002989 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002990 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002991 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 ret = -EINVAL;
2993 goto error_open;
2994 }
2995
2996 out->compr_config.codec = (struct snd_codec *)
2997 calloc(1, sizeof(struct snd_codec));
2998
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002999 if (!out->compr_config.codec) {
3000 ret = -ENOMEM;
3001 goto error_open;
3002 }
3003
vivek mehta0ea887a2015-08-26 14:01:20 -07003004 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003005 out->usecase = get_offload_usecase(adev, true);
3006 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003007 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003008 out->stream.set_callback = out_set_callback;
3009 out->stream.pause = out_pause;
3010 out->stream.resume = out_resume;
3011 out->stream.drain = out_drain;
3012 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003013 out->usecase = get_offload_usecase(adev, false);
3014 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003015 }
vivek mehta446c3962015-09-14 10:57:35 -07003016
3017 if (out->usecase == USECASE_INVALID) {
3018 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3019 ret = -EEXIST;
3020 goto error_open;
3021 }
3022
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003023 if (config->offload_info.channel_mask)
3024 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003025 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003027 config->offload_info.channel_mask = config->channel_mask;
3028 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003029 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 out->sample_rate = config->offload_info.sample_rate;
3031
Mingming Yin3ee55c62014-08-04 14:23:35 -07003032 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003034 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003035 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003036 audio_extn_dolby_get_snd_codec_id(adev, out,
3037 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003038 else
3039 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003041
3042 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3043 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003044 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003045 platform_get_pcm_offload_buffer_size(&config->offload_info);
3046 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3047 out->compr_config.fragment_size =
3048 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003049 } else {
3050 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003051 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3054 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003055 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056 out->compr_config.codec->bit_rate =
3057 config->offload_info.bit_rate;
3058 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003059 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303061 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003062 /*TODO: Do we need to change it for passthrough */
3063 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064
Manish Dewangana6fc5442015-08-24 20:30:31 +05303065 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3066 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3067 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3068 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003069 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3070 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003071 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003072 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003073 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3074 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003075
Mingming Yin3ee55c62014-08-04 14:23:35 -07003076 if (out->bit_width == 24) {
3077 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3078 }
3079
Amit Shekhar6f461b12014-08-01 14:52:58 -07003080 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303081 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003082
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3084 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003085
Mingming Yin497419f2015-07-01 16:57:32 -07003086 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003087 //this flag is set from framework only if its for PCM formats
3088 //no need to check for PCM format again
3089 out->non_blocking = 0;
3090 out->use_small_bufs = true;
3091 ALOGI("Keep write blocking for small buff: non_blockling %d",
3092 out->non_blocking);
3093 }
3094
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003095 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303096 out->send_next_track_params = false;
3097 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003098 out->offload_state = OFFLOAD_STATE_IDLE;
3099 out->playback_started = 0;
3100
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003101 audio_extn_dts_create_state_notifier_node(out->usecase);
3102
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 create_offload_callback_thread(out);
3104 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3105 __func__, config->offload_info.version,
3106 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003107 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003108 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003109 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3110 ret = voice_check_and_set_incall_music_usecase(adev, out);
3111 if (ret != 0) {
3112 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3113 __func__, ret);
3114 goto error_open;
3115 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003116 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3117 if (config->sample_rate == 0)
3118 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3119 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3120 config->sample_rate != 8000) {
3121 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3122 ret = -EINVAL;
3123 goto error_open;
3124 }
3125 out->sample_rate = config->sample_rate;
3126 out->config.rate = config->sample_rate;
3127 if (config->format == AUDIO_FORMAT_DEFAULT)
3128 config->format = AUDIO_FORMAT_PCM_16_BIT;
3129 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3130 config->format = AUDIO_FORMAT_PCM_16_BIT;
3131 ret = -EINVAL;
3132 goto error_open;
3133 }
3134 out->format = config->format;
3135 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3136 out->config = pcm_config_afe_proxy_playback;
3137 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003138 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3139 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3140 out->config = pcm_config_low_latency;
3141 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003142 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003143 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3145 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003147 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3148 format = AUDIO_FORMAT_PCM_16_BIT;
3149 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3150 out->config = pcm_config_deep_buffer;
3151 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003152 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003153 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003154 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003155 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003156 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003157 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 }
3159
Amit Shekhar1d896042014-10-03 13:16:09 -07003160 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3161 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003162 /* TODO remove this hardcoding and check why width is zero*/
3163 if (out->bit_width == 0)
3164 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003165 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3166 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003167 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303168 out->bit_width, out->channel_mask,
3169 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003170 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3171 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3172 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003173 if(adev->primary_output == NULL)
3174 adev->primary_output = out;
3175 else {
3176 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003177 ret = -EEXIST;
3178 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003179 }
3180 }
3181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 /* Check if this usecase is already existing */
3183 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003184 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3185 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003188 ret = -EEXIST;
3189 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 }
3191 pthread_mutex_unlock(&adev->lock);
3192
3193 out->stream.common.get_sample_rate = out_get_sample_rate;
3194 out->stream.common.set_sample_rate = out_set_sample_rate;
3195 out->stream.common.get_buffer_size = out_get_buffer_size;
3196 out->stream.common.get_channels = out_get_channels;
3197 out->stream.common.get_format = out_get_format;
3198 out->stream.common.set_format = out_set_format;
3199 out->stream.common.standby = out_standby;
3200 out->stream.common.dump = out_dump;
3201 out->stream.common.set_parameters = out_set_parameters;
3202 out->stream.common.get_parameters = out_get_parameters;
3203 out->stream.common.add_audio_effect = out_add_audio_effect;
3204 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3205 out->stream.get_latency = out_get_latency;
3206 out->stream.set_volume = out_set_volume;
3207 out->stream.write = out_write;
3208 out->stream.get_render_position = out_get_render_position;
3209 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003210 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003213 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003214 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215
3216 config->format = out->stream.common.get_format(&out->stream.common);
3217 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3218 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3219
3220 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303221 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003222 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003223
3224 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3225 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3226 popcount(out->channel_mask), out->playback_started);
3227
Eric Laurent994a6932013-07-17 11:51:42 -07003228 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003230
3231error_open:
3232 free(out);
3233 *stream_out = NULL;
3234 ALOGD("%s: exit: ret %d", __func__, ret);
3235 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236}
3237
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003238static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 struct audio_stream_out *stream)
3240{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003241 struct stream_out *out = (struct stream_out *)stream;
3242 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003243 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303245 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3246
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003247 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303248 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003249 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303250 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003251 if(ret != 0)
3252 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3253 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003254 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003255 out_standby(&stream->common);
3256
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003257 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003258 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003259 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003260 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003261 if (out->compr_config.codec != NULL)
3262 free(out->compr_config.codec);
3263 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003264
3265 if (adev->voice_tx_output == out)
3266 adev->voice_tx_output = NULL;
3267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 pthread_cond_destroy(&out->cond);
3269 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003271 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272}
3273
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003274static void close_compress_sessions(struct audio_device *adev)
3275{
Mingming Yin7b762e72015-03-04 13:47:32 -08003276 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303277 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003278 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003279 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303280
3281 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003282 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303283 if (is_offload_usecase(usecase->id)) {
3284 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003285 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3286 out = usecase->stream.out;
3287 pthread_mutex_unlock(&adev->lock);
3288 out_standby(&out->stream.common);
3289 pthread_mutex_lock(&adev->lock);
3290 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303291 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003292 }
3293 pthread_mutex_unlock(&adev->lock);
3294}
3295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3297{
3298 struct audio_device *adev = (struct audio_device *)dev;
3299 struct str_parms *parms;
3300 char *str;
3301 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003302 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003303 int ret;
3304 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003306 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303309 if (!parms)
3310 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003311 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3312 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303313 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303314 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303315 struct listnode *node;
3316 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303317 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303318 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003319 //close compress sessions on OFFLINE status
3320 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303321 } else if (strstr(snd_card_status, "ONLINE")) {
3322 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303323 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003324 //send dts hpx license if enabled
3325 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303326 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303327 }
3328
3329 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003330 status = voice_set_parameters(adev, parms);
3331 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003332 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003334 status = platform_set_parameters(adev->platform, parms);
3335 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003336 goto done;
3337
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003338 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3339 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003340 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3342 adev->bluetooth_nrec = true;
3343 else
3344 adev->bluetooth_nrec = false;
3345 }
3346
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003347 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3348 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3350 adev->screen_off = false;
3351 else
3352 adev->screen_off = true;
3353 }
3354
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003355 ret = str_parms_get_int(parms, "rotation", &val);
3356 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003357 bool reverse_speakers = false;
3358 switch(val) {
3359 // FIXME: note that the code below assumes that the speakers are in the correct placement
3360 // relative to the user when the device is rotated 90deg from its default rotation. This
3361 // assumption is device-specific, not platform-specific like this code.
3362 case 270:
3363 reverse_speakers = true;
3364 break;
3365 case 0:
3366 case 90:
3367 case 180:
3368 break;
3369 default:
3370 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003371 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003372 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003373 if (status == 0) {
3374 if (adev->speaker_lr_swap != reverse_speakers) {
3375 adev->speaker_lr_swap = reverse_speakers;
3376 // only update the selected device if there is active pcm playback
3377 struct audio_usecase *usecase;
3378 struct listnode *node;
3379 list_for_each(node, &adev->usecase_list) {
3380 usecase = node_to_item(node, struct audio_usecase, list);
3381 if (usecase->type == PCM_PLAYBACK) {
3382 select_devices(adev, usecase->id);
3383 break;
3384 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003385 }
3386 }
3387 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003388 }
3389
Mingming Yin514a8bc2014-07-29 15:22:21 -07003390 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3391 if (ret >= 0) {
3392 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3393 adev->bt_wb_speech_enabled = true;
3394 else
3395 adev->bt_wb_speech_enabled = false;
3396 }
3397
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003398 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3399 if (ret >= 0) {
3400 val = atoi(value);
3401 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3402 ALOGV("cache new edid");
3403 platform_cache_edid(adev->platform);
3404 }
3405 }
3406
3407 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3408 if (ret >= 0) {
3409 val = atoi(value);
3410 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3411 ALOGV("invalidate cached edid");
3412 platform_invalidate_edid(adev->platform);
3413 }
3414 }
3415
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003416 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003417
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003418done:
3419 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003420 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303421error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003422 ALOGV("%s: exit with code(%d)", __func__, status);
3423 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424}
3425
3426static char* adev_get_parameters(const struct audio_hw_device *dev,
3427 const char *keys)
3428{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003429 struct audio_device *adev = (struct audio_device *)dev;
3430 struct str_parms *reply = str_parms_create();
3431 struct str_parms *query = str_parms_create_str(keys);
3432 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303433 char value[256] = {0};
3434 int ret = 0;
3435
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003436 if (!query || !reply) {
3437 ALOGE("adev_get_parameters: failed to create query or reply");
3438 return NULL;
3439 }
3440
Naresh Tannirud7205b62014-06-20 02:54:48 +05303441 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3442 sizeof(value));
3443 if (ret >=0) {
3444 int val = 1;
3445 pthread_mutex_lock(&adev->snd_card_status.lock);
3446 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3447 val = 0;
3448 pthread_mutex_unlock(&adev->snd_card_status.lock);
3449 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3450 goto exit;
3451 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003452
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003453 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003454 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003455 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003456 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303457 pthread_mutex_unlock(&adev->lock);
3458
Naresh Tannirud7205b62014-06-20 02:54:48 +05303459exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003460 str = str_parms_to_str(reply);
3461 str_parms_destroy(query);
3462 str_parms_destroy(reply);
3463
3464 ALOGV("%s: exit: returns - %s", __func__, str);
3465 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466}
3467
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003468static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469{
3470 return 0;
3471}
3472
3473static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3474{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003475 int ret;
3476 struct audio_device *adev = (struct audio_device *)dev;
3477 pthread_mutex_lock(&adev->lock);
3478 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003479 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003480 pthread_mutex_unlock(&adev->lock);
3481 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482}
3483
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003484static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3485 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486{
3487 return -ENOSYS;
3488}
3489
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003490static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3491 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492{
3493 return -ENOSYS;
3494}
3495
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003496static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3497 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498{
3499 return -ENOSYS;
3500}
3501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003502static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3503 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
3505 return -ENOSYS;
3506}
3507
3508static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3509{
3510 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 pthread_mutex_lock(&adev->lock);
3513 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003514 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003516 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3517 voice_is_in_call(adev)) {
3518 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003519 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003520 adev->current_call_output = NULL;
3521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 }
3523 pthread_mutex_unlock(&adev->lock);
3524 return 0;
3525}
3526
3527static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3528{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003529 int ret;
3530
3531 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003532 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003533 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3534 pthread_mutex_unlock(&adev->lock);
3535
3536 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537}
3538
3539static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3540{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003541 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542 return 0;
3543}
3544
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003545static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 const struct audio_config *config)
3547{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003548 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003550 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3551 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552}
3553
3554static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003555 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 audio_devices_t devices,
3557 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003558 struct audio_stream_in **stream_in,
3559 audio_input_flags_t flags __unused,
3560 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003561 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
3563 struct audio_device *adev = (struct audio_device *)dev;
3564 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003565 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003566 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003567 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 *stream_in = NULL;
3570 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3571 return -EINVAL;
3572
3573 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003574
3575 if (!in) {
3576 ALOGE("failed to allocate input stream");
3577 return -ENOMEM;
3578 }
3579
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303580 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003581 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3582 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003584 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003585 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 in->stream.common.get_sample_rate = in_get_sample_rate;
3588 in->stream.common.set_sample_rate = in_set_sample_rate;
3589 in->stream.common.get_buffer_size = in_get_buffer_size;
3590 in->stream.common.get_channels = in_get_channels;
3591 in->stream.common.get_format = in_get_format;
3592 in->stream.common.set_format = in_set_format;
3593 in->stream.common.standby = in_standby;
3594 in->stream.common.dump = in_dump;
3595 in->stream.common.set_parameters = in_set_parameters;
3596 in->stream.common.get_parameters = in_get_parameters;
3597 in->stream.common.add_audio_effect = in_add_audio_effect;
3598 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3599 in->stream.set_gain = in_set_gain;
3600 in->stream.read = in_read;
3601 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3602
3603 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003604 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 in->standby = 1;
3607 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003608 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003609 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610
3611 /* Update config params with the requested sample rate and channels */
3612 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003613 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3614 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3615 is_low_latency = true;
3616#if LOW_LATENCY_CAPTURE_USE_CASE
3617 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3618#endif
3619 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003622 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003624 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303625 if (adev->mode != AUDIO_MODE_IN_CALL) {
3626 ret = -EINVAL;
3627 goto err_open;
3628 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003629 if (config->sample_rate == 0)
3630 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3631 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3632 config->sample_rate != 8000) {
3633 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3634 ret = -EINVAL;
3635 goto err_open;
3636 }
3637 if (config->format == AUDIO_FORMAT_DEFAULT)
3638 config->format = AUDIO_FORMAT_PCM_16_BIT;
3639 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3640 config->format = AUDIO_FORMAT_PCM_16_BIT;
3641 ret = -EINVAL;
3642 goto err_open;
3643 }
3644
3645 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3646 in->config = pcm_config_afe_proxy_record;
3647 in->config.channels = channel_count;
3648 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303649 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3650 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003651 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003652 audio_extn_compr_cap_format_supported(config->format) &&
3653 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003654 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003655 } else {
3656 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003657 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003658 buffer_size = get_input_buffer_size(config->sample_rate,
3659 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003660 channel_count,
3661 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003662 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003663 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3664 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3665 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3666 (in->config.rate == 8000 || in->config.rate == 16000) &&
3667 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3668 voice_extn_compress_voip_open_input_stream(in);
3669 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003672 /* This stream could be for sound trigger lab,
3673 get sound trigger pcm if present */
3674 audio_extn_sound_trigger_check_and_get_session(in);
3675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003677 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003678 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679
3680err_open:
3681 free(in);
3682 *stream_in = NULL;
3683 return ret;
3684}
3685
3686static void adev_close_input_stream(struct audio_hw_device *dev,
3687 struct audio_stream_in *stream)
3688{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003689 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003690 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003691 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303692
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303693 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003694
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303695 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003696 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303697
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003698 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303699 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003700 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303701 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003702 if (ret != 0)
3703 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3704 __func__, ret);
3705 } else
3706 in_standby(&stream->common);
3707
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003708 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003709 audio_extn_ssr_deinit();
3710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711
Mingming Yine62d7842013-10-25 16:26:03 -07003712 if(audio_extn_compr_cap_enabled() &&
3713 audio_extn_compr_cap_format_supported(in->config.format))
3714 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003715
3716 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 return;
3718}
3719
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003720static int adev_dump(const audio_hw_device_t *device __unused,
3721 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722{
3723 return 0;
3724}
3725
3726static int adev_close(hw_device_t *device)
3727{
3728 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003729
3730 if (!adev)
3731 return 0;
3732
3733 pthread_mutex_lock(&adev_init_lock);
3734
3735 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003736 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003737 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003738 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003739 audio_route_free(adev->audio_route);
3740 free(adev->snd_dev_ref_cnt);
3741 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003742 if (adev->adm_deinit)
3743 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003744 free(device);
3745 adev = NULL;
3746 }
3747 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 return 0;
3750}
3751
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003752/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3753 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3754 * just that it _might_ work.
3755 */
3756static int period_size_is_plausible_for_low_latency(int period_size)
3757{
3758 switch (period_size) {
3759 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003760 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003761 case 240:
3762 case 320:
3763 case 480:
3764 return 1;
3765 default:
3766 return 0;
3767 }
3768}
3769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770static int adev_open(const hw_module_t *module, const char *name,
3771 hw_device_t **device)
3772{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003773 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003775 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3777
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003778 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003779 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003780 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003781 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003782 ALOGD("%s: returning existing instance of adev", __func__);
3783 ALOGD("%s: exit", __func__);
3784 pthread_mutex_unlock(&adev_init_lock);
3785 return 0;
3786 }
3787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 adev = calloc(1, sizeof(struct audio_device));
3789
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003790 if (!adev) {
3791 pthread_mutex_unlock(&adev_init_lock);
3792 return -ENOMEM;
3793 }
3794
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003795 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3798 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3799 adev->device.common.module = (struct hw_module_t *)module;
3800 adev->device.common.close = adev_close;
3801
3802 adev->device.init_check = adev_init_check;
3803 adev->device.set_voice_volume = adev_set_voice_volume;
3804 adev->device.set_master_volume = adev_set_master_volume;
3805 adev->device.get_master_volume = adev_get_master_volume;
3806 adev->device.set_master_mute = adev_set_master_mute;
3807 adev->device.get_master_mute = adev_get_master_mute;
3808 adev->device.set_mode = adev_set_mode;
3809 adev->device.set_mic_mute = adev_set_mic_mute;
3810 adev->device.get_mic_mute = adev_get_mic_mute;
3811 adev->device.set_parameters = adev_set_parameters;
3812 adev->device.get_parameters = adev_get_parameters;
3813 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3814 adev->device.open_output_stream = adev_open_output_stream;
3815 adev->device.close_output_stream = adev_close_output_stream;
3816 adev->device.open_input_stream = adev_open_input_stream;
3817 adev->device.close_input_stream = adev_close_input_stream;
3818 adev->device.dump = adev_dump;
3819
3820 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003822 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003823 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003826 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003827 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003828 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003829 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003830 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003831 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003832 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303833 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303834 adev->perf_lock_opts[0] = 0x101;
3835 adev->perf_lock_opts[1] = 0x20E;
3836 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303837
3838 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3839 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003841 adev->platform = platform_init(adev);
3842 if (!adev->platform) {
3843 free(adev->snd_dev_ref_cnt);
3844 free(adev);
3845 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3846 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003847 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003848 return -EINVAL;
3849 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003850
Naresh Tanniru4c630392014-05-12 01:05:52 +05303851 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3852
Eric Laurentc4aef752013-09-12 17:45:53 -07003853 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3854 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3855 if (adev->visualizer_lib == NULL) {
3856 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3857 } else {
3858 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3859 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003860 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003861 "visualizer_hal_start_output");
3862 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003863 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003864 "visualizer_hal_stop_output");
3865 }
3866 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003867 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003868 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003869
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003870 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3871 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3872 if (adev->offload_effects_lib == NULL) {
3873 ALOGE("%s: DLOPEN failed for %s", __func__,
3874 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3875 } else {
3876 ALOGV("%s: DLOPEN successful for %s", __func__,
3877 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3878 adev->offload_effects_start_output =
3879 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3880 "offload_effects_bundle_hal_start_output");
3881 adev->offload_effects_stop_output =
3882 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3883 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003884 adev->offload_effects_set_hpx_state =
3885 (int (*)(bool))dlsym(adev->offload_effects_lib,
3886 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303887 adev->offload_effects_get_parameters =
3888 (void (*)(struct str_parms *, struct str_parms *))
3889 dlsym(adev->offload_effects_lib,
3890 "offload_effects_bundle_get_parameters");
3891 adev->offload_effects_set_parameters =
3892 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3893 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003894 }
3895 }
3896
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003897 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3898 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3899 if (adev->adm_lib == NULL) {
3900 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3901 } else {
3902 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3903 adev->adm_init = (adm_init_t)
3904 dlsym(adev->adm_lib, "adm_init");
3905 adev->adm_deinit = (adm_deinit_t)
3906 dlsym(adev->adm_lib, "adm_deinit");
3907 adev->adm_register_input_stream = (adm_register_input_stream_t)
3908 dlsym(adev->adm_lib, "adm_register_input_stream");
3909 adev->adm_register_output_stream = (adm_register_output_stream_t)
3910 dlsym(adev->adm_lib, "adm_register_output_stream");
3911 adev->adm_deregister_stream = (adm_deregister_stream_t)
3912 dlsym(adev->adm_lib, "adm_deregister_stream");
3913 adev->adm_request_focus = (adm_request_focus_t)
3914 dlsym(adev->adm_lib, "adm_request_focus");
3915 adev->adm_abandon_focus = (adm_abandon_focus_t)
3916 dlsym(adev->adm_lib, "adm_abandon_focus");
3917 }
3918 }
3919
Mingming Yin514a8bc2014-07-29 15:22:21 -07003920 adev->bt_wb_speech_enabled = false;
3921
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003922 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 *device = &adev->device.common;
3924
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003925 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3926 &adev->streams_output_cfg_list);
3927
Kiran Kandi910e1862013-10-29 13:29:42 -07003928 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003929
3930 char value[PROPERTY_VALUE_MAX];
3931 int trial;
3932 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3933 trial = atoi(value);
3934 if (period_size_is_plausible_for_low_latency(trial)) {
3935 pcm_config_low_latency.period_size = trial;
3936 pcm_config_low_latency.start_threshold = trial / 4;
3937 pcm_config_low_latency.avail_min = trial / 4;
3938 configured_low_latency_capture_period_size = trial;
3939 }
3940 }
3941 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3942 trial = atoi(value);
3943 if (period_size_is_plausible_for_low_latency(trial)) {
3944 configured_low_latency_capture_period_size = trial;
3945 }
3946 }
3947
vivek mehta446c3962015-09-14 10:57:35 -07003948 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003949 pthread_mutex_unlock(&adev_init_lock);
3950
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003951 if (adev->adm_init)
3952 adev->adm_data = adev->adm_init();
3953
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303954 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07003955 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 return 0;
3957}
3958
3959static struct hw_module_methods_t hal_module_methods = {
3960 .open = adev_open,
3961};
3962
3963struct audio_module HAL_MODULE_INFO_SYM = {
3964 .common = {
3965 .tag = HARDWARE_MODULE_TAG,
3966 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3967 .hal_api_version = HARDWARE_HAL_API_VERSION,
3968 .id = AUDIO_HARDWARE_MODULE_ID,
3969 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003970 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 .methods = &hal_module_methods,
3972 },
3973};