blob: e69d060fcc8b6462e734dc42d11fe76fb367837e [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",
vivek mehta446c3962015-09-14 10:57:35 -0700173#ifdef MULTIPLE_OFFLOAD_ENABLED
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700174 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
180 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
181#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700184 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700186 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700187 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800188 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800189 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700191
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700192 [USECASE_VOICE2_CALL] = "voice2-call",
193 [USECASE_VOLTE_CALL] = "volte-call",
194 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800195 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800196 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
197 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800198 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700199 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
200 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800202 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
203 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
204 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
205
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700206 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
207 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700208 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
209 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700210
211 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
212 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700213};
214
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215static const audio_usecase_t offload_usecases[] = {
216 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700217 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
vivek mehta446c3962015-09-14 10:57:35 -0700218#ifdef MULTIPLE_OFFLOAD_ENABLED
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
225 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
226#endif
227};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228
229#define STRING_TO_ENUM(string) { #string, string }
230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800231struct string_to_enum {
232 const char *name;
233 uint32_t value;
234};
235
236static const struct string_to_enum out_channels_name_to_enum_table[] = {
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
244};
245
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700246static const struct string_to_enum out_formats_name_to_enum_table[] = {
247 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
248 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
250};
251
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700252static struct audio_device *adev = NULL;
253static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700254static unsigned int audio_device_ref_count;
255
Haynes Mathew George5191a852013-09-11 14:19:36 -0700256static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800257
vivek mehtaa76401a2015-04-24 14:12:15 -0700258__attribute__ ((visibility ("default")))
259bool audio_hw_send_gain_dep_calibration(int level) {
260 bool ret_val = false;
261 ALOGV("%s: called ... ", __func__);
262
263 pthread_mutex_lock(&adev_init_lock);
264
265 if (adev != NULL && adev->platform != NULL) {
266 pthread_mutex_lock(&adev->lock);
267 ret_val = platform_send_gain_dep_cal(adev->platform, level);
268 pthread_mutex_unlock(&adev->lock);
269 } else {
270 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
271 }
272
273 pthread_mutex_unlock(&adev_init_lock);
274
275 return ret_val;
276}
277
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800278static int check_and_set_gapless_mode(struct audio_device *adev) {
279
280
281 char value[PROPERTY_VALUE_MAX] = {0};
282 bool gapless_enabled = false;
283 const char *mixer_ctl_name = "Compress Gapless Playback";
284 struct mixer_ctl *ctl;
285
286 ALOGV("%s:", __func__);
287 property_get("audio.offload.gapless.enabled", value, NULL);
288 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
289
290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
291 if (!ctl) {
292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
293 __func__, mixer_ctl_name);
294 return -EINVAL;
295 }
296
297 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
298 ALOGE("%s: Could not set gapless mode %d",
299 __func__, gapless_enabled);
300 return -EINVAL;
301 }
302 return 0;
303}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700305static bool is_supported_format(audio_format_t format)
306{
Eric Laurent86e17132013-09-12 17:49:30 -0700307 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530308 format == AUDIO_FORMAT_AAC_LC ||
309 format == AUDIO_FORMAT_AAC_HE_V1 ||
310 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530311 format == AUDIO_FORMAT_AAC_ADTS_LC ||
312 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
313 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800314 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700316 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 format == AUDIO_FORMAT_ALAC ||
319 format == AUDIO_FORMAT_APE ||
320 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800321 format == AUDIO_FORMAT_WMA ||
322 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800323 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700324
325 return false;
326}
327
328static int get_snd_codec_id(audio_format_t format)
329{
330 int id = 0;
331
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 case AUDIO_FORMAT_MP3:
334 id = SND_AUDIOCODEC_MP3;
335 break;
336 case AUDIO_FORMAT_AAC:
337 id = SND_AUDIOCODEC_AAC;
338 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530339 case AUDIO_FORMAT_AAC_ADTS:
340 id = SND_AUDIOCODEC_AAC;
341 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530342 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700343 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800344 id = SND_AUDIOCODEC_PCM;
345 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700346 case AUDIO_FORMAT_FLAC:
347 id = SND_AUDIOCODEC_FLAC;
348 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530349 case AUDIO_FORMAT_ALAC:
350 id = SND_AUDIOCODEC_ALAC;
351 break;
352 case AUDIO_FORMAT_APE:
353 id = SND_AUDIOCODEC_APE;
354 break;
355 case AUDIO_FORMAT_VORBIS:
356 id = SND_AUDIOCODEC_VORBIS;
357 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800358 case AUDIO_FORMAT_WMA:
359 id = SND_AUDIOCODEC_WMA;
360 break;
361 case AUDIO_FORMAT_WMA_PRO:
362 id = SND_AUDIOCODEC_WMA_PRO;
363 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700364 default:
Mingming Yin90310102013-11-13 16:57:00 -0800365 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700366 }
367
368 return id;
369}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800370
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530371int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530372{
373 int snd_scard_state;
374
375 if (!adev)
376 return SND_CARD_STATE_OFFLINE;
377
378 pthread_mutex_lock(&adev->snd_card_status.lock);
379 snd_scard_state = adev->snd_card_status.state;
380 pthread_mutex_unlock(&adev->snd_card_status.lock);
381
382 return snd_scard_state;
383}
384
385static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
386{
387 if (!adev)
388 return -ENOSYS;
389
390 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700391 if (adev->snd_card_status.state != snd_scard_state) {
392 adev->snd_card_status.state = snd_scard_state;
393 platform_snd_card_update(adev->platform, snd_scard_state);
394 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530395 pthread_mutex_unlock(&adev->snd_card_status.lock);
396
397 return 0;
398}
399
Avinash Vaish71a8b972014-07-24 15:36:33 +0530400static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
401 struct audio_usecase *uc_info)
402{
403 struct listnode *node;
404 struct audio_usecase *usecase;
405
406 if (uc_info == NULL)
407 return -EINVAL;
408
409 /* Re-route all voice usecases on the shared backend other than the
410 specified usecase to new snd devices */
411 list_for_each(node, &adev->usecase_list) {
412 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800413 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530414 enable_audio_route(adev, usecase);
415 }
416 return 0;
417}
418
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700419int pcm_ioctl(struct pcm *pcm, int request, ...)
420{
421 va_list ap;
422 void * arg;
423 int pcm_fd = *(int*)pcm;
424
425 va_start(ap, request);
426 arg = va_arg(ap, void *);
427 va_end(ap);
428
429 return ioctl(pcm_fd, request, arg);
430}
431
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700432int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700433 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700435 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700436 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800437
438 if (usecase == NULL)
439 return -EINVAL;
440
441 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
442
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700444 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700446 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800447
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800448#ifdef DS1_DOLBY_DAP_ENABLED
449 audio_extn_dolby_set_dmid(adev);
450 audio_extn_dolby_set_endpoint(adev);
451#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700452 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700453 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530454 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700455 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530456 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800457 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700458 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700459 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700460 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461 ALOGV("%s: exit", __func__);
462 return 0;
463}
464
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700466 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800467{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700468 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700469 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800470
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530471 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800472 return -EINVAL;
473
474 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 if (usecase->type == PCM_CAPTURE)
476 snd_device = usecase->in_snd_device;
477 else
478 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800479 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700480 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700481 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700482 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700483 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530484 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485 ALOGV("%s: exit", __func__);
486 return 0;
487}
488
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700489int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700490 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800491{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700492 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
493
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800494 if (snd_device < SND_DEVICE_MIN ||
495 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800496 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800497 return -EINVAL;
498 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700499
500 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700501
502 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
503 ALOGE("%s: Invalid sound device returned", __func__);
504 return -EINVAL;
505 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700506 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700507 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700508 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700509 return 0;
510 }
511
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700512 if (audio_extn_spkr_prot_is_enabled())
513 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700514 /* start usb playback thread */
515 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
516 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
517 audio_extn_usb_start_playback(adev);
518
519 /* start usb capture thread */
520 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
521 audio_extn_usb_start_capture(adev);
522
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800523 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700524 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
525 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
526 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
527 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700528 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
529 adev->snd_dev_ref_cnt[snd_device]--;
530 return -EINVAL;
531 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200532 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800533 if (audio_extn_spkr_prot_start_processing(snd_device)) {
534 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200535 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800536 return -EINVAL;
537 }
538 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700539 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700540 /* due to the possibility of calibration overwrite between listen
541 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700546 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700547 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700548 audio_extn_sound_trigger_update_device_status(snd_device,
549 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530550 audio_extn_listen_update_device_status(snd_device,
551 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700552 return -EINVAL;
553 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300554 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700555 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 return 0;
558}
559
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700560int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700561 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700563 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
564
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800565 if (snd_device < SND_DEVICE_MIN ||
566 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800567 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800568 return -EINVAL;
569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
571 ALOGE("%s: device ref cnt is already 0", __func__);
572 return -EINVAL;
573 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700574
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700576
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700577 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
578 ALOGE("%s: Invalid sound device returned", __func__);
579 return -EINVAL;
580 }
581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700583 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800584 /* exit usb play back thread */
585 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
586 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
587 audio_extn_usb_stop_playback();
588
589 /* exit usb capture thread */
590 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700591 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800592
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800593 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700594 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
595 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
596 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
597 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700598 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300599 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700600 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300601 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700602
Ashish Jain81eb2a82015-05-13 10:52:34 +0530603 if (snd_device == SND_DEVICE_OUT_HDMI)
604 adev->is_channel_status_set = false;
605
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200606 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700607 audio_extn_sound_trigger_update_device_status(snd_device,
608 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530609 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800610 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800613 return 0;
614}
615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616static void check_usecases_codec_backend(struct audio_device *adev,
617 struct audio_usecase *uc_info,
618 snd_device_t snd_device)
619{
620 struct listnode *node;
621 struct audio_usecase *usecase;
622 bool switch_device[AUDIO_USECASE_MAX];
623 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800624 int backend_idx = DEFAULT_CODEC_BACKEND;
625 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626
627 /*
628 * This function is to make sure that all the usecases that are active on
629 * the hardware codec backend are always routed to any one device that is
630 * handled by the hardware codec.
631 * For example, if low-latency and deep-buffer usecases are currently active
632 * on speaker and out_set_parameters(headset) is received on low-latency
633 * output, then we have to make sure deep-buffer is also switched to headset,
634 * because of the limitation that both the devices cannot be enabled
635 * at the same time as they share the same backend.
636 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700637 /*
638 * This call is to check if we need to force routing for a particular stream
639 * If there is a backend configuration change for the device when a
640 * new stream starts, then ADM needs to be closed and re-opened with the new
641 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800642 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700643 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800644 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
645 snd_device);
646 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800648 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800649 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 for (i = 0; i < AUDIO_USECASE_MAX; i++)
651 switch_device[i] = false;
652
653 list_for_each(node, &adev->usecase_list) {
654 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800655
656 if (usecase == uc_info)
657 continue;
658 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
659 ALOGV("%s: backend_idx: %d,"
660 "usecase_backend_idx: %d, curr device: %s, usecase device:"
661 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530662 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800663
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800664 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700665 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800666 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
667 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530668 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800669 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700670 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700671 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 switch_device[usecase->id] = true;
673 num_uc_to_switch++;
674 }
675 }
676
677 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700678 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530680 /* Make sure the previous devices to be disabled first and then enable the
681 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
684 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 }
687 }
688
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700689 list_for_each(node, &adev->usecase_list) {
690 usecase = node_to_item(node, struct audio_usecase, list);
691 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700692 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700693 }
694 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 /* Re-route all the usecases on the shared backend other than the
697 specified usecase to new snd devices */
698 list_for_each(node, &adev->usecase_list) {
699 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530700 /* Update the out_snd_device only for the usecases that are enabled here */
701 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
702 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530703 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 }
705 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 }
707}
708
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700709static void check_and_route_capture_usecases(struct audio_device *adev,
710 struct audio_usecase *uc_info,
711 snd_device_t snd_device)
712{
713 struct listnode *node;
714 struct audio_usecase *usecase;
715 bool switch_device[AUDIO_USECASE_MAX];
716 int i, num_uc_to_switch = 0;
717
718 /*
719 * This function is to make sure that all the active capture usecases
720 * are always routed to the same input sound device.
721 * For example, if audio-record and voice-call usecases are currently
722 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
723 * is received for voice call then we have to make sure that audio-record
724 * usecase is also switched to earpiece i.e. voice-dmic-ef,
725 * because of the limitation that two devices cannot be enabled
726 * at the same time if they share the same backend.
727 */
728 for (i = 0; i < AUDIO_USECASE_MAX; i++)
729 switch_device[i] = false;
730
731 list_for_each(node, &adev->usecase_list) {
732 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800733 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700735 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700736 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
737 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700738 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
740 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700741 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700742 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743 switch_device[usecase->id] = true;
744 num_uc_to_switch++;
745 }
746 }
747
748 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700749 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700750
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530751 /* Make sure the previous devices to be disabled first and then enable the
752 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700756 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800757 }
758 }
759
760 list_for_each(node, &adev->usecase_list) {
761 usecase = node_to_item(node, struct audio_usecase, list);
762 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700763 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 }
765 }
766
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 /* Re-route all the usecases on the shared backend other than the
768 specified usecase to new snd devices */
769 list_for_each(node, &adev->usecase_list) {
770 usecase = node_to_item(node, struct audio_usecase, list);
771 /* Update the in_snd_device only before enabling the audio route */
772 if (switch_device[usecase->id] ) {
773 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800774 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530775 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 }
777 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 }
779}
780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700782static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700784 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700785 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786
787 switch (channels) {
788 /*
789 * Do not handle stereo output in Multi-channel cases
790 * Stereo case is handled in normal playback path
791 */
792 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700793 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799 break;
800 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700801 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
804 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
805 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
806 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
807 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 break;
809 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700810 ALOGE("HDMI does not support multi channel playback");
811 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812 break;
813 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700814 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815}
816
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800817audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
818 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700819{
820 struct audio_usecase *usecase;
821 struct listnode *node;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800825 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700826 ALOGV("%s: usecase id %d", __func__, usecase->id);
827 return usecase->id;
828 }
829 }
830 return USECASE_INVALID;
831}
832
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700833struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700834 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835{
836 struct audio_usecase *usecase;
837 struct listnode *node;
838
839 list_for_each(node, &adev->usecase_list) {
840 usecase = node_to_item(node, struct audio_usecase, list);
841 if (usecase->id == uc_id)
842 return usecase;
843 }
844 return NULL;
845}
846
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800849 snd_device_t out_snd_device = SND_DEVICE_NONE;
850 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 struct audio_usecase *usecase = NULL;
852 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800853 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800854 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800855 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800856 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800858
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 usecase = get_usecase_from_list(adev, uc_id);
860 if (usecase == NULL) {
861 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
862 return -EINVAL;
863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800865 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800866 (usecase->type == VOIP_CALL) ||
867 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800869 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700870 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 usecase->devices = usecase->stream.out->devices;
872 } else {
873 /*
874 * If the voice call is active, use the sound devices of voice call usecase
875 * so that it would not result any device switch. All the usecases will
876 * be switched to new device when select_devices() is called for voice call
877 * usecase. This is to avoid switching devices for voice call when
878 * check_usecases_codec_backend() is called below.
879 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700880 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700881 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800882 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
884 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 in_snd_device = vc_usecase->in_snd_device;
886 out_snd_device = vc_usecase->out_snd_device;
887 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800888 } else if (voice_extn_compress_voip_is_active(adev)) {
889 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700890 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530891 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700892 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800893 in_snd_device = voip_usecase->in_snd_device;
894 out_snd_device = voip_usecase->out_snd_device;
895 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800896 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800897 hfp_ucid = audio_extn_hfp_get_usecase();
898 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700899 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800900 in_snd_device = hfp_usecase->in_snd_device;
901 out_snd_device = hfp_usecase->out_snd_device;
902 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 }
904 if (usecase->type == PCM_PLAYBACK) {
905 usecase->devices = usecase->stream.out->devices;
906 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700907 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700908 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800909 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700910 if (usecase->stream.out == adev->primary_output &&
911 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800912 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700913 select_devices(adev, adev->active_input->usecase);
914 }
915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 } else if (usecase->type == PCM_CAPTURE) {
917 usecase->devices = usecase->stream.in->device;
918 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700919 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530921 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
922 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
923 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
924 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700925 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700926 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700927 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
928 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700929 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700930 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700931 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700932 }
933 }
934
935 if (out_snd_device == usecase->out_snd_device &&
936 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 return 0;
938 }
939
sangwoobc677242013-08-08 16:53:43 +0900940 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700941 out_snd_device, platform_get_snd_device_name(out_snd_device),
942 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 /*
945 * Limitation: While in call, to do a device switch we need to disable
946 * and enable both RX and TX devices though one of them is same as current
947 * device.
948 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700949 if ((usecase->type == VOICE_CALL) &&
950 (usecase->in_snd_device != SND_DEVICE_NONE) &&
951 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700953 }
954
955 if (((usecase->type == VOICE_CALL) ||
956 (usecase->type == VOIP_CALL)) &&
957 (usecase->out_snd_device != SND_DEVICE_NONE)) {
958 /* Disable sidetone only if voice/voip call already exists */
959 if (voice_is_call_state_active(adev) ||
960 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700961 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800962 }
963
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 /* Disable current sound devices */
965 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700966 disable_audio_route(adev, usecase);
967 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 }
969
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700971 disable_audio_route(adev, usecase);
972 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 }
974
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800975 /* Applicable only on the targets that has external modem.
976 * New device information should be sent to modem before enabling
977 * the devices to reduce in-call device switch time.
978 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700979 if ((usecase->type == VOICE_CALL) &&
980 (usecase->in_snd_device != SND_DEVICE_NONE) &&
981 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800982 status = platform_switch_voice_call_enable_device_config(adev->platform,
983 out_snd_device,
984 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700985 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 /* Enable new sound devices */
988 if (out_snd_device != SND_DEVICE_NONE) {
989 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
990 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700991 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 }
993
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700994 if (in_snd_device != SND_DEVICE_NONE) {
995 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700996 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700997 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998
Avinash Vaish71a8b972014-07-24 15:36:33 +0530999 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001000 status = platform_switch_voice_call_device_post(adev->platform,
1001 out_snd_device,
1002 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301003 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001004 /* Enable sidetone only if voice/voip call already exists */
1005 if (voice_is_call_state_active(adev) ||
1006 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001007 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301008 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001009
sangwoo170731f2013-06-08 15:36:36 +09001010 usecase->in_snd_device = in_snd_device;
1011 usecase->out_snd_device = out_snd_device;
1012
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001014 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301015 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001016 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301017 usecase->stream.out->flags,
1018 usecase->stream.out->format,
1019 usecase->stream.out->sample_rate,
1020 usecase->stream.out->bit_width,
1021 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001022 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301023 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001024
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001025 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001026
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001027 /* Applicable only on the targets that has external modem.
1028 * Enable device command should be sent to modem only after
1029 * enabling voice call mixer controls
1030 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001031 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001032 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1033 out_snd_device,
1034 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301035 ALOGD("%s: done",__func__);
1036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037 return status;
1038}
1039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040static int stop_input_stream(struct stream_in *in)
1041{
1042 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 struct audio_usecase *uc_info;
1044 struct audio_device *adev = in->dev;
1045
Eric Laurentc8400632013-02-14 19:04:54 -08001046 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
Eric Laurent994a6932013-07-17 11:51:42 -07001048 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050 uc_info = get_usecase_from_list(adev, in->usecase);
1051 if (uc_info == NULL) {
1052 ALOGE("%s: Could not find the usecase (%d) in the list",
1053 __func__, in->usecase);
1054 return -EINVAL;
1055 }
1056
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001057 /* Close in-call recording streams */
1058 voice_check_and_stop_incall_rec_usecase(adev, in);
1059
Eric Laurent150dbfe2013-02-27 14:31:02 -08001060 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001061 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062
1063 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001064 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001066 list_remove(&uc_info->list);
1067 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068
Eric Laurent994a6932013-07-17 11:51:42 -07001069 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 return ret;
1071}
1072
1073int start_input_stream(struct stream_in *in)
1074{
1075 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001076 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 struct audio_usecase *uc_info;
1078 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301079 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080
Mingming Yin2664a5b2015-09-03 10:53:11 -07001081 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1082 if (get_usecase_from_list(adev, usecase) == NULL)
1083 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301084 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1085 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001086
Naresh Tanniru80659832014-06-04 18:17:56 +05301087
1088 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301090 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301091 goto error_config;
1092 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301093
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001094 /* Check if source matches incall recording usecase criteria */
1095 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1096 if (ret)
1097 goto error_config;
1098 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001099 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1100
1101 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1102 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1103 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1104 goto error_config;
1105 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001106
Eric Laurentb23d5282013-05-14 15:27:20 -07001107 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 if (in->pcm_device_id < 0) {
1109 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1110 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001111 ret = -EINVAL;
1112 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114
1115 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001117
1118 if (!uc_info) {
1119 ret = -ENOMEM;
1120 goto error_config;
1121 }
1122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 uc_info->id = in->usecase;
1124 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001125 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 uc_info->devices = in->device;
1127 uc_info->in_snd_device = SND_DEVICE_NONE;
1128 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001130 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301131 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133
Eric Laurentc8400632013-02-14 19:04:54 -08001134 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001135 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1136
1137 unsigned int flags = PCM_IN;
1138 unsigned int pcm_open_retry_count = 0;
1139
1140 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1141 flags |= PCM_MMAP | PCM_NOIRQ;
1142 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1143 }
1144
1145 while (1) {
1146 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1147 flags, &in->config);
1148 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1149 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1150 if (in->pcm != NULL) {
1151 pcm_close(in->pcm);
1152 in->pcm = NULL;
1153 }
1154 if (pcm_open_retry_count-- == 0) {
1155 ret = -EIO;
1156 goto error_open;
1157 }
1158 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1159 continue;
1160 }
1161 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001163
1164 ALOGV("%s: pcm_prepare", __func__);
1165 ret = pcm_prepare(in->pcm);
1166 if (ret < 0) {
1167 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1168 pcm_close(in->pcm);
1169 in->pcm = NULL;
1170 goto error_open;
1171 }
1172
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301173 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301174
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001175 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001176
Eric Laurentc8400632013-02-14 19:04:54 -08001177 return ret;
1178
1179error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001180 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301181 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001182
1183error_config:
1184 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301185 /*
1186 * sleep 50ms to allow sufficient time for kernel
1187 * drivers to recover incases like SSR.
1188 */
1189 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001191
1192 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193}
1194
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001195void lock_input_stream(struct stream_in *in)
1196{
1197 pthread_mutex_lock(&in->pre_lock);
1198 pthread_mutex_lock(&in->lock);
1199 pthread_mutex_unlock(&in->pre_lock);
1200}
1201
1202void lock_output_stream(struct stream_out *out)
1203{
1204 pthread_mutex_lock(&out->pre_lock);
1205 pthread_mutex_lock(&out->lock);
1206 pthread_mutex_unlock(&out->pre_lock);
1207}
1208
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001209/* must be called with out->lock locked */
1210static int send_offload_cmd_l(struct stream_out* out, int command)
1211{
1212 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1213
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001214 if (!cmd) {
1215 ALOGE("failed to allocate mem for command 0x%x", command);
1216 return -ENOMEM;
1217 }
1218
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001219 ALOGVV("%s %d", __func__, command);
1220
1221 cmd->cmd = command;
1222 list_add_tail(&out->offload_cmd_list, &cmd->node);
1223 pthread_cond_signal(&out->offload_cond);
1224 return 0;
1225}
1226
1227/* must be called iwth out->lock locked */
1228static void stop_compressed_output_l(struct stream_out *out)
1229{
1230 out->offload_state = OFFLOAD_STATE_IDLE;
1231 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001232 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233 if (out->compr != NULL) {
1234 compress_stop(out->compr);
1235 while (out->offload_thread_blocked) {
1236 pthread_cond_wait(&out->cond, &out->lock);
1237 }
1238 }
1239}
1240
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001241bool is_offload_usecase(audio_usecase_t uc_id)
1242{
1243 unsigned int i;
1244 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1245 if (uc_id == offload_usecases[i])
1246 return true;
1247 }
1248 return false;
1249}
1250
vivek mehta446c3962015-09-14 10:57:35 -07001251static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001252{
vivek mehta446c3962015-09-14 10:57:35 -07001253 audio_usecase_t ret_uc = USECASE_INVALID;
1254 unsigned int offload_uc_index;
1255 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1256 if (!adev->multi_offload_enable) {
1257 if (is_direct_pcm)
1258 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1259 else
1260 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001261
vivek mehta446c3962015-09-14 10:57:35 -07001262 pthread_mutex_lock(&adev->lock);
1263 if (get_usecase_from_list(adev, ret_uc) != NULL)
1264 ret_uc = USECASE_INVALID;
1265 pthread_mutex_unlock(&adev->lock);
1266
1267 return ret_uc;
1268 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001269
1270 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001271 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1272 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1273 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1274 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001275 break;
1276 }
1277 }
vivek mehta446c3962015-09-14 10:57:35 -07001278
1279 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1280 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001281}
1282
1283static void free_offload_usecase(struct audio_device *adev,
1284 audio_usecase_t uc_id)
1285{
vivek mehta446c3962015-09-14 10:57:35 -07001286 unsigned int offload_uc_index;
1287 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1288
1289 if (!adev->multi_offload_enable)
1290 return;
1291
1292 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1293 if (offload_usecases[offload_uc_index] == uc_id) {
1294 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001295 break;
1296 }
1297 }
1298 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1299}
1300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301static void *offload_thread_loop(void *context)
1302{
1303 struct stream_out *out = (struct stream_out *) context;
1304 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001305 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1308 set_sched_policy(0, SP_FOREGROUND);
1309 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1310
1311 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001312 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 for (;;) {
1314 struct offload_cmd *cmd = NULL;
1315 stream_callback_event_t event;
1316 bool send_callback = false;
1317
1318 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1319 __func__, list_empty(&out->offload_cmd_list),
1320 out->offload_state);
1321 if (list_empty(&out->offload_cmd_list)) {
1322 ALOGV("%s SLEEPING", __func__);
1323 pthread_cond_wait(&out->offload_cond, &out->lock);
1324 ALOGV("%s RUNNING", __func__);
1325 continue;
1326 }
1327
1328 item = list_head(&out->offload_cmd_list);
1329 cmd = node_to_item(item, struct offload_cmd, node);
1330 list_remove(item);
1331
1332 ALOGVV("%s STATE %d CMD %d out->compr %p",
1333 __func__, out->offload_state, cmd->cmd, out->compr);
1334
1335 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1336 free(cmd);
1337 break;
1338 }
1339
1340 if (out->compr == NULL) {
1341 ALOGE("%s: Compress handle is NULL", __func__);
1342 pthread_cond_signal(&out->cond);
1343 continue;
1344 }
1345 out->offload_thread_blocked = true;
1346 pthread_mutex_unlock(&out->lock);
1347 send_callback = false;
1348 switch(cmd->cmd) {
1349 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001350 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001351 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001352 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001353 send_callback = true;
1354 event = STREAM_CBK_EVENT_WRITE_READY;
1355 break;
1356 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001357 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301358 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001359 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301360 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001361 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301362 if (ret < 0)
1363 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301364 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301365 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001366 compress_drain(out->compr);
1367 else
1368 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301369 if (ret != -ENETRESET) {
1370 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301371 pthread_mutex_lock(&out->lock);
1372 out->send_new_metadata = 1;
1373 out->send_next_track_params = true;
1374 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301375 event = STREAM_CBK_EVENT_DRAIN_READY;
1376 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1377 } else
1378 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001379 break;
1380 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001381 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001382 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001383 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001384 send_callback = true;
1385 event = STREAM_CBK_EVENT_DRAIN_READY;
1386 break;
1387 default:
1388 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1389 break;
1390 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001391 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392 out->offload_thread_blocked = false;
1393 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001394 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001395 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001396 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001397 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001398 free(cmd);
1399 }
1400
1401 pthread_cond_signal(&out->cond);
1402 while (!list_empty(&out->offload_cmd_list)) {
1403 item = list_head(&out->offload_cmd_list);
1404 list_remove(item);
1405 free(node_to_item(item, struct offload_cmd, node));
1406 }
1407 pthread_mutex_unlock(&out->lock);
1408
1409 return NULL;
1410}
1411
1412static int create_offload_callback_thread(struct stream_out *out)
1413{
1414 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1415 list_init(&out->offload_cmd_list);
1416 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1417 offload_thread_loop, out);
1418 return 0;
1419}
1420
1421static int destroy_offload_callback_thread(struct stream_out *out)
1422{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001423 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001424 stop_compressed_output_l(out);
1425 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1426
1427 pthread_mutex_unlock(&out->lock);
1428 pthread_join(out->offload_thread, (void **) NULL);
1429 pthread_cond_destroy(&out->offload_cond);
1430
1431 return 0;
1432}
1433
Eric Laurent07eeafd2013-10-06 12:52:49 -07001434static bool allow_hdmi_channel_config(struct audio_device *adev)
1435{
1436 struct listnode *node;
1437 struct audio_usecase *usecase;
1438 bool ret = true;
1439
1440 list_for_each(node, &adev->usecase_list) {
1441 usecase = node_to_item(node, struct audio_usecase, list);
1442 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1443 /*
1444 * If voice call is already existing, do not proceed further to avoid
1445 * disabling/enabling both RX and TX devices, CSD calls, etc.
1446 * Once the voice call done, the HDMI channels can be configured to
1447 * max channels of remaining use cases.
1448 */
1449 if (usecase->id == USECASE_VOICE_CALL) {
1450 ALOGD("%s: voice call is active, no change in HDMI channels",
1451 __func__);
1452 ret = false;
1453 break;
1454 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1455 ALOGD("%s: multi channel playback is active, "
1456 "no change in HDMI channels", __func__);
1457 ret = false;
1458 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001459 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001460 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001461 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1462 ", no change in HDMI channels", __func__,
1463 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001464 ret = false;
1465 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001466 }
1467 }
1468 }
1469 return ret;
1470}
1471
1472static int check_and_set_hdmi_channels(struct audio_device *adev,
1473 unsigned int channels)
1474{
1475 struct listnode *node;
1476 struct audio_usecase *usecase;
1477
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001478 unsigned int supported_channels = platform_edid_get_max_channels(
1479 adev->platform);
1480 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001481 /* Check if change in HDMI channel config is allowed */
1482 if (!allow_hdmi_channel_config(adev))
1483 return 0;
1484
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001485 if (channels > supported_channels)
1486 channels = supported_channels;
1487
Eric Laurent07eeafd2013-10-06 12:52:49 -07001488 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001489 ALOGD("%s: Requested channels are same as current channels(%d)",
1490 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001491 return 0;
1492 }
1493
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001494 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001495 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001496 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001497 adev->cur_hdmi_channels = channels;
1498
1499 /*
1500 * Deroute all the playback streams routed to HDMI so that
1501 * the back end is deactivated. Note that backend will not
1502 * be deactivated if any one stream is connected to it.
1503 */
1504 list_for_each(node, &adev->usecase_list) {
1505 usecase = node_to_item(node, struct audio_usecase, list);
1506 if (usecase->type == PCM_PLAYBACK &&
1507 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001508 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001509 }
1510 }
1511
1512 /*
1513 * Enable all the streams disabled above. Now the HDMI backend
1514 * will be activated with new channel configuration
1515 */
1516 list_for_each(node, &adev->usecase_list) {
1517 usecase = node_to_item(node, struct audio_usecase, list);
1518 if (usecase->type == PCM_PLAYBACK &&
1519 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001520 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001521 }
1522 }
1523
1524 return 0;
1525}
1526
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527static int stop_output_stream(struct stream_out *out)
1528{
1529 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 struct audio_usecase *uc_info;
1531 struct audio_device *adev = out->dev;
1532
Eric Laurent994a6932013-07-17 11:51:42 -07001533 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 uc_info = get_usecase_from_list(adev, out->usecase);
1536 if (uc_info == NULL) {
1537 ALOGE("%s: Could not find the usecase (%d) in the list",
1538 __func__, out->usecase);
1539 return -EINVAL;
1540 }
1541
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001542 if (is_offload_usecase(out->usecase) &&
1543 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001544 if (adev->visualizer_stop_output != NULL)
1545 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001546
1547 audio_extn_dts_remove_state_notifier_node(out->usecase);
1548
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001549 if (adev->offload_effects_stop_output != NULL)
1550 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1551 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001552
Eric Laurent150dbfe2013-02-27 14:31:02 -08001553 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001554 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555
1556 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001557 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001559 list_remove(&uc_info->list);
1560 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001562 if (is_offload_usecase(out->usecase) &&
1563 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1564 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1565 ALOGV("Disable passthrough , reset mixer to pcm");
1566 /* NO_PASSTHROUGH */
1567 out->compr_config.codec->compr_passthr = 0;
1568 audio_extn_dolby_set_hdmi_config(adev, out);
1569 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1570 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001571 /* Must be called after removing the usecase from list */
1572 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1573 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1574
Eric Laurent994a6932013-07-17 11:51:42 -07001575 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576 return ret;
1577}
1578
1579int start_output_stream(struct stream_out *out)
1580{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001582 int sink_channels = 0;
1583 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 struct audio_usecase *uc_info;
1585 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301586 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001588 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1589 ret = -EINVAL;
1590 goto error_config;
1591 }
1592
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301593 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1594 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1595 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301596
Naresh Tanniru80659832014-06-04 18:17:56 +05301597 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301598 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301599 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301600 goto error_config;
1601 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301602
Eric Laurentb23d5282013-05-14 15:27:20 -07001603 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 if (out->pcm_device_id < 0) {
1605 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1606 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001607 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001608 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 }
1610
1611 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001612
1613 if (!uc_info) {
1614 ret = -ENOMEM;
1615 goto error_config;
1616 }
1617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 uc_info->id = out->usecase;
1619 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001620 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 uc_info->devices = out->devices;
1622 uc_info->in_snd_device = SND_DEVICE_NONE;
1623 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001624 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001625 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001626 if (is_offload_usecase(out->usecase)) {
1627 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001628 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1629 }
1630 }
Mingming Yin9c041392014-05-01 15:37:31 -07001631 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1632 if (!strncmp("true", prop_value, 4)) {
1633 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001634 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1635 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001636 check_and_set_hdmi_channels(adev, sink_channels);
1637 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001638 if (is_offload_usecase(out->usecase)) {
1639 unsigned int ch_count = out->compr_config.codec->ch_in;
1640 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1641 /* backend channel config for passthrough stream is stereo */
1642 ch_count = 2;
1643 check_and_set_hdmi_channels(adev, ch_count);
1644 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001645 check_and_set_hdmi_channels(adev, out->config.channels);
1646 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001647 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001648 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001649 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001651 select_devices(adev, out->usecase);
1652
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001653 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1654 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001655 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001656 unsigned int flags = PCM_OUT;
1657 unsigned int pcm_open_retry_count = 0;
1658 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1659 flags |= PCM_MMAP | PCM_NOIRQ;
1660 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1661 } else
1662 flags |= PCM_MONOTONIC;
1663
1664 while (1) {
1665 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1666 flags, &out->config);
1667 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1668 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1669 if (out->pcm != NULL) {
1670 pcm_close(out->pcm);
1671 out->pcm = NULL;
1672 }
1673 if (pcm_open_retry_count-- == 0) {
1674 ret = -EIO;
1675 goto error_open;
1676 }
1677 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1678 continue;
1679 }
1680 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001682
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001683 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1684 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001685
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001686 ALOGV("%s: pcm_prepare", __func__);
1687 if (pcm_is_ready(out->pcm)) {
1688 ret = pcm_prepare(out->pcm);
1689 if (ret < 0) {
1690 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1691 pcm_close(out->pcm);
1692 out->pcm = NULL;
1693 goto error_open;
1694 }
1695 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001697 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1698 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001700 out->compr = compress_open(adev->snd_card,
1701 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001702 COMPRESS_IN, &out->compr_config);
1703 if (out->compr && !is_compress_ready(out->compr)) {
1704 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1705 compress_close(out->compr);
1706 out->compr = NULL;
1707 ret = -EIO;
1708 goto error_open;
1709 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301710 /* compress_open sends params of the track, so reset the flag here */
1711 out->is_compr_metadata_avail = false;
1712
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 if (out->offload_callback)
1714 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001715
Fred Oh3f43e742015-03-04 18:42:34 -08001716 /* Since small bufs uses blocking writes, a write will be blocked
1717 for the default max poll time (20s) in the event of an SSR.
1718 Reduce the poll time to observe and deal with SSR faster.
1719 */
1720 if (out->use_small_bufs) {
1721 compress_set_max_poll_wait(out->compr, 1000);
1722 }
1723
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001724 audio_extn_dts_create_state_notifier_node(out->usecase);
1725 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1726 popcount(out->channel_mask),
1727 out->playback_started);
1728
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001729#ifdef DS1_DOLBY_DDP_ENABLED
1730 if (audio_extn_is_dolby_format(out->format))
1731 audio_extn_dolby_send_ddp_endp_params(adev);
1732#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001733 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1734 if (adev->visualizer_start_output != NULL)
1735 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1736 if (adev->offload_effects_start_output != NULL)
1737 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001738 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001739 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001741
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001742 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001747error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301748 /*
1749 * sleep 50ms to allow sufficient time for kernel
1750 * drivers to recover incases like SSR.
1751 */
1752 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001753 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754}
1755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756static int check_input_parameters(uint32_t sample_rate,
1757 audio_format_t format,
1758 int channel_count)
1759{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001760 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001763 !voice_extn_compress_voip_is_format_supported(format) &&
1764 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001765
1766 switch (channel_count) {
1767 case 1:
1768 case 2:
1769 case 6:
1770 break;
1771 default:
1772 ret = -EINVAL;
1773 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
1775 switch (sample_rate) {
1776 case 8000:
1777 case 11025:
1778 case 12000:
1779 case 16000:
1780 case 22050:
1781 case 24000:
1782 case 32000:
1783 case 44100:
1784 case 48000:
1785 break;
1786 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001787 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 }
1789
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001790 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791}
1792
1793static size_t get_input_buffer_size(uint32_t sample_rate,
1794 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001795 int channel_count,
1796 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797{
1798 size_t size = 0;
1799
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001800 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1801 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001803 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001804 if (is_low_latency)
1805 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001806 /* ToDo: should use frame_size computed based on the format and
1807 channel_count here. */
1808 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001810 /* make sure the size is multiple of 32 bytes
1811 * At 48 kHz mono 16-bit PCM:
1812 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1813 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1814 */
1815 size += 0x1f;
1816 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001817
1818 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819}
1820
1821static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1822{
1823 struct stream_out *out = (struct stream_out *)stream;
1824
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826}
1827
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001828static int out_set_sample_rate(struct audio_stream *stream __unused,
1829 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830{
1831 return -ENOSYS;
1832}
1833
1834static size_t out_get_buffer_size(const struct audio_stream *stream)
1835{
1836 struct stream_out *out = (struct stream_out *)stream;
1837
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001838 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001840 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1841 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001843 return out->config.period_size *
1844 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845}
1846
1847static uint32_t out_get_channels(const struct audio_stream *stream)
1848{
1849 struct stream_out *out = (struct stream_out *)stream;
1850
1851 return out->channel_mask;
1852}
1853
1854static audio_format_t out_get_format(const struct audio_stream *stream)
1855{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 struct stream_out *out = (struct stream_out *)stream;
1857
1858 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859}
1860
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001861static int out_set_format(struct audio_stream *stream __unused,
1862 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863{
1864 return -ENOSYS;
1865}
1866
1867static int out_standby(struct audio_stream *stream)
1868{
1869 struct stream_out *out = (struct stream_out *)stream;
1870 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001871
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301872 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1873 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001874 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1875 /* Ignore standby in case of voip call because the voip output
1876 * stream is closed in adev_close_output_stream()
1877 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301878 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001879 return 0;
1880 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001882 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001884 if (adev->adm_deregister_stream)
1885 adev->adm_deregister_stream(adev->adm_data, out->handle);
1886
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001887 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001889 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890 if (out->pcm) {
1891 pcm_close(out->pcm);
1892 out->pcm = NULL;
1893 }
1894 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001895 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301897 out->send_next_track_params = false;
1898 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001899 out->gapless_mdata.encoder_delay = 0;
1900 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001901 if (out->compr != NULL) {
1902 compress_close(out->compr);
1903 out->compr = NULL;
1904 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001905 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001907 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 }
1909 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001910 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 return 0;
1912}
1913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001914static int out_dump(const struct audio_stream *stream __unused,
1915 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916{
1917 return 0;
1918}
1919
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001920static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1921{
1922 int ret = 0;
1923 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001924
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001925 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001926 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001927 return -EINVAL;
1928 }
1929
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301930 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001931
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001932 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1933 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301934 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001935 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1937 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301938 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001939 }
1940
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001941 ALOGV("%s new encoder delay %u and padding %u", __func__,
1942 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1943
1944 return 0;
1945}
1946
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001947static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1948{
1949 return out == adev->primary_output || out == adev->voice_tx_output;
1950}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1953{
1954 struct stream_out *out = (struct stream_out *)stream;
1955 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001956 struct audio_usecase *usecase;
1957 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 struct str_parms *parms;
1959 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001960 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001961 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962
sangwoobc677242013-08-08 16:53:43 +09001963 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301966 if (!parms)
1967 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001968 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1969 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001971 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001972 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001974 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301975 * When HDMI cable is unplugged/usb hs is disconnected the
1976 * music playback is paused and the policy manager sends routing=0
1977 * But the audioflingercontinues to write data until standby time
1978 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979 * Avoid this by routing audio to speaker until standby.
1980 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301981 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1982 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001983 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001984 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1985 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 }
1987
1988 /*
1989 * select_devices() call below switches all the usecases on the same
1990 * backend to the new device. Refer to check_usecases_codec_backend() in
1991 * the select_devices(). But how do we undo this?
1992 *
1993 * For example, music playback is active on headset (deep-buffer usecase)
1994 * and if we go to ringtones and select a ringtone, low-latency usecase
1995 * will be started on headset+speaker. As we can't enable headset+speaker
1996 * and headset devices at the same time, select_devices() switches the music
1997 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1998 * So when the ringtone playback is completed, how do we undo the same?
1999 *
2000 * We are relying on the out_set_parameters() call on deep-buffer output,
2001 * once the ringtone playback is ended.
2002 * NOTE: We should not check if the current devices are same as new devices.
2003 * Because select_devices() must be called to switch back the music
2004 * playback to headset.
2005 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002006 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002007 out->devices = val;
2008
2009 if (!out->standby)
2010 select_devices(adev, out->usecase);
2011
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) {
2077 strcat(value, "|");
2078 }
2079 strcat(value, out_channels_name_to_enum_table[j].name);
2080 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
2097 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2098 if (ret >= 0) {
2099 value[0] = '\0';
2100 i = 0;
2101 first = true;
2102 while (out->supported_formats[i] != 0) {
2103 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2104 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2105 if (!first) {
2106 strcat(value, "|");
2107 }
2108 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2109 first = false;
2110 break;
2111 }
2112 }
2113 i++;
2114 }
2115 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2116 str = str_parms_to_str(reply);
2117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 str_parms_destroy(query);
2119 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002120 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 return str;
2122}
2123
2124static uint32_t out_get_latency(const struct audio_stream_out *stream)
2125{
2126 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002127 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128
Alexy Josephaa54c872014-12-03 02:46:47 -08002129 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002130 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002131 } else {
2132 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002134 }
2135
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302136 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002137 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138}
2139
2140static int out_set_volume(struct audio_stream_out *stream, float left,
2141 float right)
2142{
Eric Laurenta9024de2013-04-04 09:19:12 -07002143 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 int volume[2];
2145
Eric Laurenta9024de2013-04-04 09:19:12 -07002146 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2147 /* only take left channel into account: the API is for stereo anyway */
2148 out->muted = (left == 0.0f);
2149 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002150 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002151 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2152 /*
2153 * Set mute or umute on HDMI passthrough stream.
2154 * Only take left channel into account.
2155 * Mute is 0 and unmute 1
2156 */
2157 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2158 } else {
2159 char mixer_ctl_name[128];
2160 struct audio_device *adev = out->dev;
2161 struct mixer_ctl *ctl;
2162 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002163 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002165 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2166 "Compress Playback %d Volume", pcm_device_id);
2167 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2168 if (!ctl) {
2169 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2170 __func__, mixer_ctl_name);
2171 return -EINVAL;
2172 }
2173 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2174 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2175 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2176 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002178 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 return -ENOSYS;
2181}
2182
2183static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2184 size_t bytes)
2185{
2186 struct stream_out *out = (struct stream_out *)stream;
2187 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302188 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002189 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002191 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302192
Naresh Tanniru80659832014-06-04 18:17:56 +05302193 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002194 // increase written size during SSR to avoid mismatch
2195 // with the written frames count in AF
2196 if (!is_offload_usecase(out->usecase))
2197 out->written += bytes / (out->config.channels * sizeof(short));
2198
Naresh Tanniru80659832014-06-04 18:17:56 +05302199 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302200 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302201 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302202 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002203 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302204 //during SSR for compress usecase we should return error to flinger
2205 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2206 pthread_mutex_unlock(&out->lock);
2207 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302208 }
2209 }
2210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002212 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002213 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002214 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2215 ret = voice_extn_compress_voip_start_output_stream(out);
2216 else
2217 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002218 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002221 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 goto exit;
2223 }
vivek mehta446c3962015-09-14 10:57:35 -07002224 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002225 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227
Ashish Jain81eb2a82015-05-13 10:52:34 +05302228 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2229 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2230 adev->is_channel_status_set = true;
2231 }
2232
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002233 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002234 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002235 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002236 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002237 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2238 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302239 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2240 ALOGD("copl(%p):send next track params in gapless", out);
2241 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2242 out->send_next_track_params = false;
2243 out->is_compr_metadata_avail = false;
2244 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 }
2246
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302248 if (ret < 0)
2249 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002250 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002251 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302252 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302254 } else if (-ENETRESET == ret) {
2255 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2256 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2257 pthread_mutex_unlock(&out->lock);
2258 out_standby(&out->stream.common);
2259 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002260 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302261 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002263 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 out->playback_started = 1;
2265 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002266
2267 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2268 popcount(out->channel_mask),
2269 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002270 }
2271 pthread_mutex_unlock(&out->lock);
2272 return ret;
2273 } else {
2274 if (out->pcm) {
2275 if (out->muted)
2276 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002277
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002279
2280 if (adev->adm_request_focus)
2281 adev->adm_request_focus(adev->adm_data, out->handle);
2282
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002283 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2284 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2285 else
2286 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002287
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302288 if (ret < 0)
2289 ret = -errno;
2290 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002291 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002292
2293 if (adev->adm_abandon_focus)
2294 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 }
2297
2298exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302299 /* ToDo: There may be a corner case when SSR happens back to back during
2300 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302301 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302302 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302303 }
2304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 pthread_mutex_unlock(&out->lock);
2306
2307 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002308 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002309 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302310 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302311 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302312 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302313 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302314 out->standby = true;
2315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002317 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302318 out_get_sample_rate(&out->stream.common));
2319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 }
2321 return bytes;
2322}
2323
2324static int out_get_render_position(const struct audio_stream_out *stream,
2325 uint32_t *dsp_frames)
2326{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302328 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002329
2330 if (dsp_frames == NULL)
2331 return -EINVAL;
2332
2333 *dsp_frames = 0;
2334 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002335 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002336 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302338 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302340 if (ret < 0)
2341 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 ALOGVV("%s rendered frames %d sample_rate %d",
2343 __func__, *dsp_frames, out->sample_rate);
2344 }
2345 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302346 if (-ENETRESET == ret) {
2347 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2348 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2349 return -EINVAL;
2350 } else if(ret < 0) {
2351 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2352 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302353 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2354 /*
2355 * Handle corner case where compress session is closed during SSR
2356 * and timestamp is queried
2357 */
2358 ALOGE(" ERROR: sound card not active, return error");
2359 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302360 } else {
2361 return 0;
2362 }
Zhou Song32a556e2015-05-05 10:46:56 +08002363 } else if (audio_is_linear_pcm(out->format)) {
2364 *dsp_frames = out->written;
2365 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 } else
2367 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368}
2369
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002370static int out_add_audio_effect(const struct audio_stream *stream __unused,
2371 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372{
2373 return 0;
2374}
2375
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002376static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2377 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378{
2379 return 0;
2380}
2381
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002382static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2383 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384{
2385 return -EINVAL;
2386}
2387
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002388static int out_get_presentation_position(const struct audio_stream_out *stream,
2389 uint64_t *frames, struct timespec *timestamp)
2390{
2391 struct stream_out *out = (struct stream_out *)stream;
2392 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002393 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002394
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002395 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002396
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002397 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002398 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302399 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002400 &out->sample_rate);
2401 ALOGVV("%s rendered frames %ld sample_rate %d",
2402 __func__, dsp_frames, out->sample_rate);
2403 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302404 if (ret < 0)
2405 ret = -errno;
2406 if (-ENETRESET == ret) {
2407 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2408 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2409 ret = -EINVAL;
2410 } else
2411 ret = 0;
2412
Eric Laurent949a0892013-09-20 09:20:13 -07002413 /* this is the best we can do */
2414 clock_gettime(CLOCK_MONOTONIC, timestamp);
2415 }
2416 } else {
2417 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002418 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002419 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2420 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002421 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002422 // This adjustment accounts for buffering after app processor.
2423 // It is based on estimated DSP latency per use case, rather than exact.
2424 signed_frames -=
2425 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2426
Eric Laurent949a0892013-09-20 09:20:13 -07002427 // It would be unusual for this value to be negative, but check just in case ...
2428 if (signed_frames >= 0) {
2429 *frames = signed_frames;
2430 ret = 0;
2431 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002432 }
2433 }
2434 }
2435
2436 pthread_mutex_unlock(&out->lock);
2437
2438 return ret;
2439}
2440
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441static int out_set_callback(struct audio_stream_out *stream,
2442 stream_callback_t callback, void *cookie)
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
2445
2446 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002447 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 out->offload_callback = callback;
2449 out->offload_cookie = cookie;
2450 pthread_mutex_unlock(&out->lock);
2451 return 0;
2452}
2453
2454static int out_pause(struct audio_stream_out* stream)
2455{
2456 struct stream_out *out = (struct stream_out *)stream;
2457 int status = -ENOSYS;
2458 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002459 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002460 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002461 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302463 struct audio_device *adev = out->dev;
2464 int snd_scard_state = get_snd_card_state(adev);
2465
2466 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2467 status = compress_pause(out->compr);
2468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002470
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302471 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002472 audio_extn_dts_notify_playback_state(out->usecase, 0,
2473 out->sample_rate, popcount(out->channel_mask),
2474 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475 }
2476 pthread_mutex_unlock(&out->lock);
2477 }
2478 return status;
2479}
2480
2481static int out_resume(struct audio_stream_out* stream)
2482{
2483 struct stream_out *out = (struct stream_out *)stream;
2484 int status = -ENOSYS;
2485 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002486 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002487 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002489 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302491 struct audio_device *adev = out->dev;
2492 int snd_scard_state = get_snd_card_state(adev);
2493
2494 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2495 status = compress_resume(out->compr);
2496
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002498
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302499 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002500 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2501 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 }
2503 pthread_mutex_unlock(&out->lock);
2504 }
2505 return status;
2506}
2507
2508static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2509{
2510 struct stream_out *out = (struct stream_out *)stream;
2511 int status = -ENOSYS;
2512 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002513 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002514 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2516 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2517 else
2518 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2519 pthread_mutex_unlock(&out->lock);
2520 }
2521 return status;
2522}
2523
2524static int out_flush(struct audio_stream_out* stream)
2525{
2526 struct stream_out *out = (struct stream_out *)stream;
2527 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002528 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002529 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002530 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002531 stop_compressed_output_l(out);
2532 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002533 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 return 0;
2535 }
2536 return -ENOSYS;
2537}
2538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539/** audio_stream_in implementation **/
2540static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2541{
2542 struct stream_in *in = (struct stream_in *)stream;
2543
2544 return in->config.rate;
2545}
2546
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002547static int in_set_sample_rate(struct audio_stream *stream __unused,
2548 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549{
2550 return -ENOSYS;
2551}
2552
2553static size_t in_get_buffer_size(const struct audio_stream *stream)
2554{
2555 struct stream_in *in = (struct stream_in *)stream;
2556
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002557 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2558 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002559 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2560 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002561
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002562 return in->config.period_size *
2563 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564}
2565
2566static uint32_t in_get_channels(const struct audio_stream *stream)
2567{
2568 struct stream_in *in = (struct stream_in *)stream;
2569
2570 return in->channel_mask;
2571}
2572
2573static audio_format_t in_get_format(const struct audio_stream *stream)
2574{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002575 struct stream_in *in = (struct stream_in *)stream;
2576
2577 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578}
2579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002580static int in_set_format(struct audio_stream *stream __unused,
2581 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582{
2583 return -ENOSYS;
2584}
2585
2586static int in_standby(struct audio_stream *stream)
2587{
2588 struct stream_in *in = (struct stream_in *)stream;
2589 struct audio_device *adev = in->dev;
2590 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302591 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2592 stream, in->usecase, use_case_table[in->usecase]);
2593
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002594 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2595 /* Ignore standby in case of voip call because the voip input
2596 * stream is closed in adev_close_input_stream()
2597 */
2598 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2599 return status;
2600 }
2601
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002602 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002603 if (!in->standby && in->is_st_session) {
2604 ALOGD("%s: sound trigger pcm stop lab", __func__);
2605 audio_extn_sound_trigger_stop_lab(in);
2606 in->standby = 1;
2607 }
2608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002610 if (adev->adm_deregister_stream)
2611 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2612
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002613 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002615 if (in->pcm) {
2616 pcm_close(in->pcm);
2617 in->pcm = NULL;
2618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002620 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 }
2622 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002623 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 return status;
2625}
2626
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002627static int in_dump(const struct audio_stream *stream __unused,
2628 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629{
2630 return 0;
2631}
2632
2633static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2634{
2635 struct stream_in *in = (struct stream_in *)stream;
2636 struct audio_device *adev = in->dev;
2637 struct str_parms *parms;
2638 char *str;
2639 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002640 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302642 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 parms = str_parms_create_str(kvpairs);
2644
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302645 if (!parms)
2646 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002647 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002648 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002649
2650 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2651 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 val = atoi(value);
2653 /* no audio source uses val == 0 */
2654 if ((in->source != val) && (val != 0)) {
2655 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002656 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2657 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2658 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2659 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002660 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002661 err = voice_extn_compress_voip_open_input_stream(in);
2662 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002663 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002664 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002665 }
2666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 }
2668 }
2669
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002670 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2671 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002673 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 in->device = val;
2675 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002676 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002677 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 }
2679 }
2680
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002681done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002683 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
2685 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302686error:
Eric Laurent994a6932013-07-17 11:51:42 -07002687 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 return ret;
2689}
2690
2691static char* in_get_parameters(const struct audio_stream *stream,
2692 const char *keys)
2693{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002694 struct stream_in *in = (struct stream_in *)stream;
2695 struct str_parms *query = str_parms_create_str(keys);
2696 char *str;
2697 char value[256];
2698 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002699
2700 if (!query || !reply) {
2701 ALOGE("in_get_parameters: failed to create query or reply");
2702 return NULL;
2703 }
2704
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002705 ALOGV("%s: enter: keys - %s", __func__, keys);
2706
2707 voice_extn_in_get_parameters(in, query, reply);
2708
2709 str = str_parms_to_str(reply);
2710 str_parms_destroy(query);
2711 str_parms_destroy(reply);
2712
2713 ALOGV("%s: exit: returns - %s", __func__, str);
2714 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715}
2716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002717static int in_set_gain(struct audio_stream_in *stream __unused,
2718 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719{
2720 return 0;
2721}
2722
2723static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2724 size_t bytes)
2725{
2726 struct stream_in *in = (struct stream_in *)stream;
2727 struct audio_device *adev = in->dev;
2728 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302729 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002731 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302732
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002733 if (in->is_st_session) {
2734 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2735 /* Read from sound trigger HAL */
2736 audio_extn_sound_trigger_read(in, buffer, bytes);
2737 pthread_mutex_unlock(&in->lock);
2738 return bytes;
2739 }
2740
2741 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2742 ALOGD(" %s: sound card is not active/SSR state", __func__);
2743 ret= -EIO;;
2744 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302745 }
2746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002748 pthread_mutex_lock(&adev->lock);
2749 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2750 ret = voice_extn_compress_voip_start_input_stream(in);
2751 else
2752 ret = start_input_stream(in);
2753 pthread_mutex_unlock(&adev->lock);
2754 if (ret != 0) {
2755 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 }
2757 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002758 if (adev->adm_register_input_stream)
2759 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002762 if (adev->adm_request_focus)
2763 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002766 if (audio_extn_ssr_get_enabled() &&
2767 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002768 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002769 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2770 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002771 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2772 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002773 else
2774 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302775 if (ret < 0)
2776 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 }
2778
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002779 if (adev->adm_abandon_focus)
2780 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 /*
2783 * Instead of writing zeroes here, we could trust the hardware
2784 * to always provide zeroes when muted.
2785 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302786 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2787 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 memset(buffer, 0, bytes);
2789
2790exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302791 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302792 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002793 if (-ENETRESET == ret)
2794 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 pthread_mutex_unlock(&in->lock);
2797
2798 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302799 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302800 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302801 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302802 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302803 in->standby = true;
2804 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302805 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002807 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002808 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302809 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 }
2811 return bytes;
2812}
2813
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002814static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815{
2816 return 0;
2817}
2818
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002819static int add_remove_audio_effect(const struct audio_stream *stream,
2820 effect_handle_t effect,
2821 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002823 struct stream_in *in = (struct stream_in *)stream;
2824 int status = 0;
2825 effect_descriptor_t desc;
2826
2827 status = (*effect)->get_descriptor(effect, &desc);
2828 if (status != 0)
2829 return status;
2830
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002831 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002832 pthread_mutex_lock(&in->dev->lock);
2833 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2834 in->enable_aec != enable &&
2835 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2836 in->enable_aec = enable;
2837 if (!in->standby)
2838 select_devices(in->dev, in->usecase);
2839 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002840 if (in->enable_ns != enable &&
2841 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2842 in->enable_ns = enable;
2843 if (!in->standby)
2844 select_devices(in->dev, in->usecase);
2845 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002846 pthread_mutex_unlock(&in->dev->lock);
2847 pthread_mutex_unlock(&in->lock);
2848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 return 0;
2850}
2851
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002852static int in_add_audio_effect(const struct audio_stream *stream,
2853 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854{
Eric Laurent994a6932013-07-17 11:51:42 -07002855 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002856 return add_remove_audio_effect(stream, effect, true);
2857}
2858
2859static int in_remove_audio_effect(const struct audio_stream *stream,
2860 effect_handle_t effect)
2861{
Eric Laurent994a6932013-07-17 11:51:42 -07002862 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002863 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864}
2865
2866static int adev_open_output_stream(struct audio_hw_device *dev,
2867 audio_io_handle_t handle,
2868 audio_devices_t devices,
2869 audio_output_flags_t flags,
2870 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002871 struct audio_stream_out **stream_out,
2872 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873{
2874 struct audio_device *adev = (struct audio_device *)dev;
2875 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002876 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002877 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302880
2881 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2882 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002883 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302884 return -EINVAL;
2885 }
2886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2888
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302889 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2890 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2891 devices, flags, &out->stream);
2892
2893
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002894 if (!out) {
2895 return -ENOMEM;
2896 }
2897
Haynes Mathew George204045b2015-02-25 20:32:03 -08002898 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002899 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002900 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 if (devices == AUDIO_DEVICE_NONE)
2903 devices = AUDIO_DEVICE_OUT_SPEAKER;
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 out->flags = flags;
2906 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002907 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002908 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909 out->sample_rate = config->sample_rate;
2910 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2911 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002912 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002913 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002914 out->non_blocking = 0;
2915 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916
2917 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002918 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2919 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002920 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2921 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2922
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002923 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002924 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2925 ret = read_hdmi_channel_masks(out);
2926
2927 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2928 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002929 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002930 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002931 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002932
2933 if (config->sample_rate == 0)
2934 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2935 if (config->channel_mask == 0)
2936 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2937
2938 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2941 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002943 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002945 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2946 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002947 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002948 ret = voice_extn_compress_voip_open_output_stream(out);
2949 if (ret != 0) {
2950 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2951 __func__, ret);
2952 goto error_open;
2953 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002954 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2955 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2956
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2958 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2959 ALOGE("%s: Unsupported Offload information", __func__);
2960 ret = -EINVAL;
2961 goto error_open;
2962 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002963
2964 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2965 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2966 ALOGV("read and update_pass through formats");
2967 ret = audio_extn_dolby_update_passt_formats(adev, out);
2968 if(ret != 0) {
2969 goto error_open;
2970 }
2971 if(config->offload_info.format == 0)
2972 config->offload_info.format = out->supported_formats[0];
2973 }
2974
Mingming Yin90310102013-11-13 16:57:00 -08002975 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002976 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002977 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 ret = -EINVAL;
2979 goto error_open;
2980 }
2981
2982 out->compr_config.codec = (struct snd_codec *)
2983 calloc(1, sizeof(struct snd_codec));
2984
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002985 if (!out->compr_config.codec) {
2986 ret = -ENOMEM;
2987 goto error_open;
2988 }
2989
vivek mehta0ea887a2015-08-26 14:01:20 -07002990 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07002991 out->usecase = get_offload_usecase(adev, true);
2992 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07002993 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07002994 out->stream.set_callback = out_set_callback;
2995 out->stream.pause = out_pause;
2996 out->stream.resume = out_resume;
2997 out->stream.drain = out_drain;
2998 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07002999 out->usecase = get_offload_usecase(adev, false);
3000 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003001 }
vivek mehta446c3962015-09-14 10:57:35 -07003002
3003 if (out->usecase == USECASE_INVALID) {
3004 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3005 ret = -EEXIST;
3006 goto error_open;
3007 }
3008
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003009 if (config->offload_info.channel_mask)
3010 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003011 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003013 config->offload_info.channel_mask = config->channel_mask;
3014 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003015 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003016 out->sample_rate = config->offload_info.sample_rate;
3017
Mingming Yin3ee55c62014-08-04 14:23:35 -07003018 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003019
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003020 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003021 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003022 audio_extn_dolby_get_snd_codec_id(adev, out,
3023 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003024 else
3025 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003027
3028 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3029 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003030 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003031 platform_get_pcm_offload_buffer_size(&config->offload_info);
3032 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3033 out->compr_config.fragment_size =
3034 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003035 } else {
3036 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003037 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003038 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3040 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003041 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042 out->compr_config.codec->bit_rate =
3043 config->offload_info.bit_rate;
3044 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003045 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303047 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003048 /*TODO: Do we need to change it for passthrough */
3049 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050
Manish Dewangana6fc5442015-08-24 20:30:31 +05303051 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3052 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3053 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3054 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003055 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3056 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003057 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003058 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003059 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3060 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003061
Mingming Yin3ee55c62014-08-04 14:23:35 -07003062 if (out->bit_width == 24) {
3063 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3064 }
3065
Amit Shekhar6f461b12014-08-01 14:52:58 -07003066 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303067 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003068
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3070 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003071
Mingming Yin497419f2015-07-01 16:57:32 -07003072 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003073 //this flag is set from framework only if its for PCM formats
3074 //no need to check for PCM format again
3075 out->non_blocking = 0;
3076 out->use_small_bufs = true;
3077 ALOGI("Keep write blocking for small buff: non_blockling %d",
3078 out->non_blocking);
3079 }
3080
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003081 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303082 out->send_next_track_params = false;
3083 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003084 out->offload_state = OFFLOAD_STATE_IDLE;
3085 out->playback_started = 0;
3086
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003087 audio_extn_dts_create_state_notifier_node(out->usecase);
3088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 create_offload_callback_thread(out);
3090 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3091 __func__, config->offload_info.version,
3092 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003093 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003094 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003095 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3096 ret = voice_check_and_set_incall_music_usecase(adev, out);
3097 if (ret != 0) {
3098 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3099 __func__, ret);
3100 goto error_open;
3101 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003102 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3103 if (config->sample_rate == 0)
3104 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3105 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3106 config->sample_rate != 8000) {
3107 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3108 ret = -EINVAL;
3109 goto error_open;
3110 }
3111 out->sample_rate = config->sample_rate;
3112 out->config.rate = config->sample_rate;
3113 if (config->format == AUDIO_FORMAT_DEFAULT)
3114 config->format = AUDIO_FORMAT_PCM_16_BIT;
3115 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3116 config->format = AUDIO_FORMAT_PCM_16_BIT;
3117 ret = -EINVAL;
3118 goto error_open;
3119 }
3120 out->format = config->format;
3121 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3122 out->config = pcm_config_afe_proxy_playback;
3123 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003124 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3125 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3126 out->config = pcm_config_low_latency;
3127 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003128 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003129 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3131 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003132 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003133 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3134 format = AUDIO_FORMAT_PCM_16_BIT;
3135 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3136 out->config = pcm_config_deep_buffer;
3137 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003138 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003139 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003140 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003141 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003142 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003143 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 }
3145
Amit Shekhar1d896042014-10-03 13:16:09 -07003146 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3147 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003148 /* TODO remove this hardcoding and check why width is zero*/
3149 if (out->bit_width == 0)
3150 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003151 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3152 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003153 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003154 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003155 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3156 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3157 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003158 if(adev->primary_output == NULL)
3159 adev->primary_output = out;
3160 else {
3161 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003162 ret = -EEXIST;
3163 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003164 }
3165 }
3166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 /* Check if this usecase is already existing */
3168 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003169 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3170 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003173 ret = -EEXIST;
3174 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 }
3176 pthread_mutex_unlock(&adev->lock);
3177
3178 out->stream.common.get_sample_rate = out_get_sample_rate;
3179 out->stream.common.set_sample_rate = out_set_sample_rate;
3180 out->stream.common.get_buffer_size = out_get_buffer_size;
3181 out->stream.common.get_channels = out_get_channels;
3182 out->stream.common.get_format = out_get_format;
3183 out->stream.common.set_format = out_set_format;
3184 out->stream.common.standby = out_standby;
3185 out->stream.common.dump = out_dump;
3186 out->stream.common.set_parameters = out_set_parameters;
3187 out->stream.common.get_parameters = out_get_parameters;
3188 out->stream.common.add_audio_effect = out_add_audio_effect;
3189 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3190 out->stream.get_latency = out_get_latency;
3191 out->stream.set_volume = out_set_volume;
3192 out->stream.write = out_write;
3193 out->stream.get_render_position = out_get_render_position;
3194 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003195 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003198 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003199 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200
3201 config->format = out->stream.common.get_format(&out->stream.common);
3202 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3203 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3204
3205 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303206 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003207 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003208
3209 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3210 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3211 popcount(out->channel_mask), out->playback_started);
3212
Eric Laurent994a6932013-07-17 11:51:42 -07003213 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003215
3216error_open:
3217 free(out);
3218 *stream_out = NULL;
3219 ALOGD("%s: exit: ret %d", __func__, ret);
3220 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221}
3222
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003223static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224 struct audio_stream_out *stream)
3225{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003226 struct stream_out *out = (struct stream_out *)stream;
3227 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003228 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003229
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303230 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3231
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003232 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303233 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003234 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303235 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003236 if(ret != 0)
3237 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3238 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003239 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003240 out_standby(&stream->common);
3241
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003242 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003243 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003245 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246 if (out->compr_config.codec != NULL)
3247 free(out->compr_config.codec);
3248 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003249
3250 if (adev->voice_tx_output == out)
3251 adev->voice_tx_output = NULL;
3252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 pthread_cond_destroy(&out->cond);
3254 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003256 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257}
3258
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003259static void close_compress_sessions(struct audio_device *adev)
3260{
Mingming Yin7b762e72015-03-04 13:47:32 -08003261 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303262 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003263 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003264 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303265
3266 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003267 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303268 if (is_offload_usecase(usecase->id)) {
3269 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003270 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3271 out = usecase->stream.out;
3272 pthread_mutex_unlock(&adev->lock);
3273 out_standby(&out->stream.common);
3274 pthread_mutex_lock(&adev->lock);
3275 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303276 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003277 }
3278 pthread_mutex_unlock(&adev->lock);
3279}
3280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3282{
3283 struct audio_device *adev = (struct audio_device *)dev;
3284 struct str_parms *parms;
3285 char *str;
3286 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003287 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003288 int ret;
3289 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003291 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303294 if (!parms)
3295 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003296 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3297 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303298 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303299 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303300 struct listnode *node;
3301 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303302 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303303 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003304 //close compress sessions on OFFLINE status
3305 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303306 } else if (strstr(snd_card_status, "ONLINE")) {
3307 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303308 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003309 //send dts hpx license if enabled
3310 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303311 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303312 }
3313
3314 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003315 status = voice_set_parameters(adev, parms);
3316 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003317 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003319 status = platform_set_parameters(adev->platform, parms);
3320 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003321 goto done;
3322
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003323 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3324 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003325 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3327 adev->bluetooth_nrec = true;
3328 else
3329 adev->bluetooth_nrec = false;
3330 }
3331
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003332 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3333 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3335 adev->screen_off = false;
3336 else
3337 adev->screen_off = true;
3338 }
3339
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003340 ret = str_parms_get_int(parms, "rotation", &val);
3341 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003342 bool reverse_speakers = false;
3343 switch(val) {
3344 // FIXME: note that the code below assumes that the speakers are in the correct placement
3345 // relative to the user when the device is rotated 90deg from its default rotation. This
3346 // assumption is device-specific, not platform-specific like this code.
3347 case 270:
3348 reverse_speakers = true;
3349 break;
3350 case 0:
3351 case 90:
3352 case 180:
3353 break;
3354 default:
3355 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003356 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003357 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003358 if (status == 0) {
3359 if (adev->speaker_lr_swap != reverse_speakers) {
3360 adev->speaker_lr_swap = reverse_speakers;
3361 // only update the selected device if there is active pcm playback
3362 struct audio_usecase *usecase;
3363 struct listnode *node;
3364 list_for_each(node, &adev->usecase_list) {
3365 usecase = node_to_item(node, struct audio_usecase, list);
3366 if (usecase->type == PCM_PLAYBACK) {
3367 select_devices(adev, usecase->id);
3368 break;
3369 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003370 }
3371 }
3372 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003373 }
3374
Mingming Yin514a8bc2014-07-29 15:22:21 -07003375 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3376 if (ret >= 0) {
3377 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3378 adev->bt_wb_speech_enabled = true;
3379 else
3380 adev->bt_wb_speech_enabled = false;
3381 }
3382
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003383 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3384 if (ret >= 0) {
3385 val = atoi(value);
3386 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3387 ALOGV("cache new edid");
3388 platform_cache_edid(adev->platform);
3389 }
3390 }
3391
3392 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3393 if (ret >= 0) {
3394 val = atoi(value);
3395 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3396 ALOGV("invalidate cached edid");
3397 platform_invalidate_edid(adev->platform);
3398 }
3399 }
3400
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003401 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003402
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003403done:
3404 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003405 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303406error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003407 ALOGV("%s: exit with code(%d)", __func__, status);
3408 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409}
3410
3411static char* adev_get_parameters(const struct audio_hw_device *dev,
3412 const char *keys)
3413{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003414 struct audio_device *adev = (struct audio_device *)dev;
3415 struct str_parms *reply = str_parms_create();
3416 struct str_parms *query = str_parms_create_str(keys);
3417 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303418 char value[256] = {0};
3419 int ret = 0;
3420
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003421 if (!query || !reply) {
3422 ALOGE("adev_get_parameters: failed to create query or reply");
3423 return NULL;
3424 }
3425
Naresh Tannirud7205b62014-06-20 02:54:48 +05303426 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3427 sizeof(value));
3428 if (ret >=0) {
3429 int val = 1;
3430 pthread_mutex_lock(&adev->snd_card_status.lock);
3431 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3432 val = 0;
3433 pthread_mutex_unlock(&adev->snd_card_status.lock);
3434 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3435 goto exit;
3436 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003437
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003438 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003439 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003440 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003441 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303442 pthread_mutex_unlock(&adev->lock);
3443
Naresh Tannirud7205b62014-06-20 02:54:48 +05303444exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003445 str = str_parms_to_str(reply);
3446 str_parms_destroy(query);
3447 str_parms_destroy(reply);
3448
3449 ALOGV("%s: exit: returns - %s", __func__, str);
3450 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451}
3452
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003453static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454{
3455 return 0;
3456}
3457
3458static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3459{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003460 int ret;
3461 struct audio_device *adev = (struct audio_device *)dev;
3462 pthread_mutex_lock(&adev->lock);
3463 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003464 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003465 pthread_mutex_unlock(&adev->lock);
3466 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467}
3468
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003469static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3470 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471{
3472 return -ENOSYS;
3473}
3474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003475static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3476 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477{
3478 return -ENOSYS;
3479}
3480
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003481static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3482 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483{
3484 return -ENOSYS;
3485}
3486
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003487static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3488 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489{
3490 return -ENOSYS;
3491}
3492
3493static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3494{
3495 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 pthread_mutex_lock(&adev->lock);
3498 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003499 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003501 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3502 voice_is_in_call(adev)) {
3503 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003504 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003505 adev->current_call_output = NULL;
3506 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 }
3508 pthread_mutex_unlock(&adev->lock);
3509 return 0;
3510}
3511
3512static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3513{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003514 int ret;
3515
3516 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003517 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003518 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3519 pthread_mutex_unlock(&adev->lock);
3520
3521 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522}
3523
3524static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3525{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003526 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 return 0;
3528}
3529
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003530static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 const struct audio_config *config)
3532{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003533 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003535 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3536 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537}
3538
3539static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003540 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541 audio_devices_t devices,
3542 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003543 struct audio_stream_in **stream_in,
3544 audio_input_flags_t flags __unused,
3545 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003546 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547{
3548 struct audio_device *adev = (struct audio_device *)dev;
3549 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003550 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003551 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003552 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 *stream_in = NULL;
3555 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3556 return -EINVAL;
3557
3558 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003559
3560 if (!in) {
3561 ALOGE("failed to allocate input stream");
3562 return -ENOMEM;
3563 }
3564
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303565 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003566 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3567 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003569 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003570 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572 in->stream.common.get_sample_rate = in_get_sample_rate;
3573 in->stream.common.set_sample_rate = in_set_sample_rate;
3574 in->stream.common.get_buffer_size = in_get_buffer_size;
3575 in->stream.common.get_channels = in_get_channels;
3576 in->stream.common.get_format = in_get_format;
3577 in->stream.common.set_format = in_set_format;
3578 in->stream.common.standby = in_standby;
3579 in->stream.common.dump = in_dump;
3580 in->stream.common.set_parameters = in_set_parameters;
3581 in->stream.common.get_parameters = in_get_parameters;
3582 in->stream.common.add_audio_effect = in_add_audio_effect;
3583 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3584 in->stream.set_gain = in_set_gain;
3585 in->stream.read = in_read;
3586 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3587
3588 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003589 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 in->standby = 1;
3592 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003593 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003594 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595
3596 /* Update config params with the requested sample rate and channels */
3597 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003598 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3599 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3600 is_low_latency = true;
3601#if LOW_LATENCY_CAPTURE_USE_CASE
3602 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3603#endif
3604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003607 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003609 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303610 if (adev->mode != AUDIO_MODE_IN_CALL) {
3611 ret = -EINVAL;
3612 goto err_open;
3613 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003614 if (config->sample_rate == 0)
3615 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3616 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3617 config->sample_rate != 8000) {
3618 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3619 ret = -EINVAL;
3620 goto err_open;
3621 }
3622 if (config->format == AUDIO_FORMAT_DEFAULT)
3623 config->format = AUDIO_FORMAT_PCM_16_BIT;
3624 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3625 config->format = AUDIO_FORMAT_PCM_16_BIT;
3626 ret = -EINVAL;
3627 goto err_open;
3628 }
3629
3630 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3631 in->config = pcm_config_afe_proxy_record;
3632 in->config.channels = channel_count;
3633 in->config.rate = config->sample_rate;
3634 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003635 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003636 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003637 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3638 ret = -EINVAL;
3639 goto err_open;
3640 }
3641 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003642 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003643 }
Mingming Yine62d7842013-10-25 16:26:03 -07003644 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003645 audio_extn_compr_cap_format_supported(config->format) &&
3646 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003647 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003648 } else {
3649 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003650 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003651 buffer_size = get_input_buffer_size(config->sample_rate,
3652 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003653 channel_count,
3654 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003655 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003656 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3657 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3658 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3659 (in->config.rate == 8000 || in->config.rate == 16000) &&
3660 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3661 voice_extn_compress_voip_open_input_stream(in);
3662 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003665 /* This stream could be for sound trigger lab,
3666 get sound trigger pcm if present */
3667 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303668 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003671 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003672 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673
3674err_open:
3675 free(in);
3676 *stream_in = NULL;
3677 return ret;
3678}
3679
3680static void adev_close_input_stream(struct audio_hw_device *dev,
3681 struct audio_stream_in *stream)
3682{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003683 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003684 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003685 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303686
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303687 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003688
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303689 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003690 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303691
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003692 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303693 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003694 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303695 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003696 if (ret != 0)
3697 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3698 __func__, ret);
3699 } else
3700 in_standby(&stream->common);
3701
Mingming Yin7b762e72015-03-04 13:47:32 -08003702 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003703 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003704 audio_extn_ssr_deinit();
3705 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
Mingming Yine62d7842013-10-25 16:26:03 -07003707 if(audio_extn_compr_cap_enabled() &&
3708 audio_extn_compr_cap_format_supported(in->config.format))
3709 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003710
3711 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 return;
3713}
3714
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003715static int adev_dump(const audio_hw_device_t *device __unused,
3716 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717{
3718 return 0;
3719}
3720
3721static int adev_close(hw_device_t *device)
3722{
3723 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003724
3725 if (!adev)
3726 return 0;
3727
3728 pthread_mutex_lock(&adev_init_lock);
3729
3730 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003731 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003732 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003733 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003734 audio_route_free(adev->audio_route);
3735 free(adev->snd_dev_ref_cnt);
3736 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003737 if (adev->adm_deinit)
3738 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003739 free(device);
3740 adev = NULL;
3741 }
3742 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 return 0;
3745}
3746
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003747/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3748 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3749 * just that it _might_ work.
3750 */
3751static int period_size_is_plausible_for_low_latency(int period_size)
3752{
3753 switch (period_size) {
3754 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003755 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003756 case 240:
3757 case 320:
3758 case 480:
3759 return 1;
3760 default:
3761 return 0;
3762 }
3763}
3764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765static int adev_open(const hw_module_t *module, const char *name,
3766 hw_device_t **device)
3767{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003768 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003770 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3772
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003773 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003774 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003775 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003776 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003777 ALOGD("%s: returning existing instance of adev", __func__);
3778 ALOGD("%s: exit", __func__);
3779 pthread_mutex_unlock(&adev_init_lock);
3780 return 0;
3781 }
3782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 adev = calloc(1, sizeof(struct audio_device));
3784
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003785 if (!adev) {
3786 pthread_mutex_unlock(&adev_init_lock);
3787 return -ENOMEM;
3788 }
3789
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003790 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3793 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3794 adev->device.common.module = (struct hw_module_t *)module;
3795 adev->device.common.close = adev_close;
3796
3797 adev->device.init_check = adev_init_check;
3798 adev->device.set_voice_volume = adev_set_voice_volume;
3799 adev->device.set_master_volume = adev_set_master_volume;
3800 adev->device.get_master_volume = adev_get_master_volume;
3801 adev->device.set_master_mute = adev_set_master_mute;
3802 adev->device.get_master_mute = adev_get_master_mute;
3803 adev->device.set_mode = adev_set_mode;
3804 adev->device.set_mic_mute = adev_set_mic_mute;
3805 adev->device.get_mic_mute = adev_get_mic_mute;
3806 adev->device.set_parameters = adev_set_parameters;
3807 adev->device.get_parameters = adev_get_parameters;
3808 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3809 adev->device.open_output_stream = adev_open_output_stream;
3810 adev->device.close_output_stream = adev_close_output_stream;
3811 adev->device.open_input_stream = adev_open_input_stream;
3812 adev->device.close_input_stream = adev_close_input_stream;
3813 adev->device.dump = adev_dump;
3814
3815 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003817 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003818 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003821 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003822 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003823 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003824 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003825 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003826 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003827 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303828 adev->is_channel_status_set = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303829
3830 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3831 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003833 adev->platform = platform_init(adev);
3834 if (!adev->platform) {
3835 free(adev->snd_dev_ref_cnt);
3836 free(adev);
3837 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3838 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003839 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003840 return -EINVAL;
3841 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003842
Naresh Tanniru4c630392014-05-12 01:05:52 +05303843 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3844
Eric Laurentc4aef752013-09-12 17:45:53 -07003845 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3846 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3847 if (adev->visualizer_lib == NULL) {
3848 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3849 } else {
3850 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3851 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003852 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003853 "visualizer_hal_start_output");
3854 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003855 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003856 "visualizer_hal_stop_output");
3857 }
3858 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003859 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003860 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003861
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003862 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3863 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3864 if (adev->offload_effects_lib == NULL) {
3865 ALOGE("%s: DLOPEN failed for %s", __func__,
3866 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3867 } else {
3868 ALOGV("%s: DLOPEN successful for %s", __func__,
3869 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3870 adev->offload_effects_start_output =
3871 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3872 "offload_effects_bundle_hal_start_output");
3873 adev->offload_effects_stop_output =
3874 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3875 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003876 adev->offload_effects_set_hpx_state =
3877 (int (*)(bool))dlsym(adev->offload_effects_lib,
3878 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303879 adev->offload_effects_get_parameters =
3880 (void (*)(struct str_parms *, struct str_parms *))
3881 dlsym(adev->offload_effects_lib,
3882 "offload_effects_bundle_get_parameters");
3883 adev->offload_effects_set_parameters =
3884 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3885 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003886 }
3887 }
3888
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003889 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3890 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3891 if (adev->adm_lib == NULL) {
3892 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3893 } else {
3894 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3895 adev->adm_init = (adm_init_t)
3896 dlsym(adev->adm_lib, "adm_init");
3897 adev->adm_deinit = (adm_deinit_t)
3898 dlsym(adev->adm_lib, "adm_deinit");
3899 adev->adm_register_input_stream = (adm_register_input_stream_t)
3900 dlsym(adev->adm_lib, "adm_register_input_stream");
3901 adev->adm_register_output_stream = (adm_register_output_stream_t)
3902 dlsym(adev->adm_lib, "adm_register_output_stream");
3903 adev->adm_deregister_stream = (adm_deregister_stream_t)
3904 dlsym(adev->adm_lib, "adm_deregister_stream");
3905 adev->adm_request_focus = (adm_request_focus_t)
3906 dlsym(adev->adm_lib, "adm_request_focus");
3907 adev->adm_abandon_focus = (adm_abandon_focus_t)
3908 dlsym(adev->adm_lib, "adm_abandon_focus");
3909 }
3910 }
3911
Mingming Yin514a8bc2014-07-29 15:22:21 -07003912 adev->bt_wb_speech_enabled = false;
3913
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003914 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 *device = &adev->device.common;
3916
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003917 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3918 &adev->streams_output_cfg_list);
3919
Kiran Kandi910e1862013-10-29 13:29:42 -07003920 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003921
3922 char value[PROPERTY_VALUE_MAX];
3923 int trial;
3924 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3925 trial = atoi(value);
3926 if (period_size_is_plausible_for_low_latency(trial)) {
3927 pcm_config_low_latency.period_size = trial;
3928 pcm_config_low_latency.start_threshold = trial / 4;
3929 pcm_config_low_latency.avail_min = trial / 4;
3930 configured_low_latency_capture_period_size = trial;
3931 }
3932 }
3933 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3934 trial = atoi(value);
3935 if (period_size_is_plausible_for_low_latency(trial)) {
3936 configured_low_latency_capture_period_size = trial;
3937 }
3938 }
3939
vivek mehta446c3962015-09-14 10:57:35 -07003940 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003941 pthread_mutex_unlock(&adev_init_lock);
3942
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003943 if (adev->adm_init)
3944 adev->adm_data = adev->adm_init();
3945
Eric Laurent994a6932013-07-17 11:51:42 -07003946 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947 return 0;
3948}
3949
3950static struct hw_module_methods_t hal_module_methods = {
3951 .open = adev_open,
3952};
3953
3954struct audio_module HAL_MODULE_INFO_SYM = {
3955 .common = {
3956 .tag = HARDWARE_MODULE_TAG,
3957 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3958 .hal_api_version = HARDWARE_HAL_API_VERSION,
3959 .id = AUDIO_HARDWARE_MODULE_ID,
3960 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003961 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 .methods = &hal_module_methods,
3963 },
3964};