blob: b30e3bc952c41647a19c8ec5fa5097a8d7ef2044 [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);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700455 audio_extn_utils_send_audio_calibration(adev, usecase);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700456 audio_extn_utils_send_app_type_cfg(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 Papothifa9d2282015-09-17 01:53:25 +05301131 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1132 adev->perf_lock_opts,
1133 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001135
Eric Laurentc8400632013-02-14 19:04:54 -08001136 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001137 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1138
1139 unsigned int flags = PCM_IN;
1140 unsigned int pcm_open_retry_count = 0;
1141
1142 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1143 flags |= PCM_MMAP | PCM_NOIRQ;
1144 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1145 }
1146
1147 while (1) {
1148 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1149 flags, &in->config);
1150 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1151 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1152 if (in->pcm != NULL) {
1153 pcm_close(in->pcm);
1154 in->pcm = NULL;
1155 }
1156 if (pcm_open_retry_count-- == 0) {
1157 ret = -EIO;
1158 goto error_open;
1159 }
1160 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1161 continue;
1162 }
1163 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001165
1166 ALOGV("%s: pcm_prepare", __func__);
1167 ret = pcm_prepare(in->pcm);
1168 if (ret < 0) {
1169 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1170 pcm_close(in->pcm);
1171 in->pcm = NULL;
1172 goto error_open;
1173 }
1174
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301175 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001176 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001177
Eric Laurentc8400632013-02-14 19:04:54 -08001178 return ret;
1179
1180error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301181 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001183error_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
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301651 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1652 adev->perf_lock_opts,
1653 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001654 select_devices(adev, out->usecase);
1655
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001656 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1657 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001658 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001659 unsigned int flags = PCM_OUT;
1660 unsigned int pcm_open_retry_count = 0;
1661 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1662 flags |= PCM_MMAP | PCM_NOIRQ;
1663 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1664 } else
1665 flags |= PCM_MONOTONIC;
1666
1667 while (1) {
1668 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1669 flags, &out->config);
1670 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1671 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1672 if (out->pcm != NULL) {
1673 pcm_close(out->pcm);
1674 out->pcm = NULL;
1675 }
1676 if (pcm_open_retry_count-- == 0) {
1677 ret = -EIO;
1678 goto error_open;
1679 }
1680 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1681 continue;
1682 }
1683 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001685
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001686 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1687 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001688
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001689 ALOGV("%s: pcm_prepare", __func__);
1690 if (pcm_is_ready(out->pcm)) {
1691 ret = pcm_prepare(out->pcm);
1692 if (ret < 0) {
1693 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1694 pcm_close(out->pcm);
1695 out->pcm = NULL;
1696 goto error_open;
1697 }
1698 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001700 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1701 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001703 out->compr = compress_open(adev->snd_card,
1704 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001705 COMPRESS_IN, &out->compr_config);
1706 if (out->compr && !is_compress_ready(out->compr)) {
1707 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1708 compress_close(out->compr);
1709 out->compr = NULL;
1710 ret = -EIO;
1711 goto error_open;
1712 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301713 /* compress_open sends params of the track, so reset the flag here */
1714 out->is_compr_metadata_avail = false;
1715
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001716 if (out->offload_callback)
1717 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001718
Fred Oh3f43e742015-03-04 18:42:34 -08001719 /* Since small bufs uses blocking writes, a write will be blocked
1720 for the default max poll time (20s) in the event of an SSR.
1721 Reduce the poll time to observe and deal with SSR faster.
1722 */
1723 if (out->use_small_bufs) {
1724 compress_set_max_poll_wait(out->compr, 1000);
1725 }
1726
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001727 audio_extn_dts_create_state_notifier_node(out->usecase);
1728 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1729 popcount(out->channel_mask),
1730 out->playback_started);
1731
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001732#ifdef DS1_DOLBY_DDP_ENABLED
1733 if (audio_extn_is_dolby_format(out->format))
1734 audio_extn_dolby_send_ddp_endp_params(adev);
1735#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001736 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1737 if (adev->visualizer_start_output != NULL)
1738 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1739 if (adev->offload_effects_start_output != NULL)
1740 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001741 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301744 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001745 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301749 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001751error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301752 /*
1753 * sleep 50ms to allow sufficient time for kernel
1754 * drivers to recover incases like SSR.
1755 */
1756 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001757 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758}
1759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760static int check_input_parameters(uint32_t sample_rate,
1761 audio_format_t format,
1762 int channel_count)
1763{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001764 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001766 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001767 !voice_extn_compress_voip_is_format_supported(format) &&
1768 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001769
1770 switch (channel_count) {
1771 case 1:
1772 case 2:
1773 case 6:
1774 break;
1775 default:
1776 ret = -EINVAL;
1777 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778
1779 switch (sample_rate) {
1780 case 8000:
1781 case 11025:
1782 case 12000:
1783 case 16000:
1784 case 22050:
1785 case 24000:
1786 case 32000:
1787 case 44100:
1788 case 48000:
1789 break;
1790 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001791 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 }
1793
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001794 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795}
1796
1797static size_t get_input_buffer_size(uint32_t sample_rate,
1798 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001799 int channel_count,
1800 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801{
1802 size_t size = 0;
1803
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001804 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1805 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001807 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001808 if (is_low_latency)
1809 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001810 /* ToDo: should use frame_size computed based on the format and
1811 channel_count here. */
1812 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001814 /* make sure the size is multiple of 32 bytes
1815 * At 48 kHz mono 16-bit PCM:
1816 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1817 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1818 */
1819 size += 0x1f;
1820 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001821
1822 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823}
1824
1825static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1826{
1827 struct stream_out *out = (struct stream_out *)stream;
1828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830}
1831
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001832static int out_set_sample_rate(struct audio_stream *stream __unused,
1833 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834{
1835 return -ENOSYS;
1836}
1837
1838static size_t out_get_buffer_size(const struct audio_stream *stream)
1839{
1840 struct stream_out *out = (struct stream_out *)stream;
1841
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001842 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001843 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001844 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1845 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001846
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001847 return out->config.period_size *
1848 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849}
1850
1851static uint32_t out_get_channels(const struct audio_stream *stream)
1852{
1853 struct stream_out *out = (struct stream_out *)stream;
1854
1855 return out->channel_mask;
1856}
1857
1858static audio_format_t out_get_format(const struct audio_stream *stream)
1859{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001860 struct stream_out *out = (struct stream_out *)stream;
1861
1862 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863}
1864
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001865static int out_set_format(struct audio_stream *stream __unused,
1866 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867{
1868 return -ENOSYS;
1869}
1870
1871static int out_standby(struct audio_stream *stream)
1872{
1873 struct stream_out *out = (struct stream_out *)stream;
1874 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001875
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301876 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1877 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001878 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1879 /* Ignore standby in case of voip call because the voip output
1880 * stream is closed in adev_close_output_stream()
1881 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301882 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001883 return 0;
1884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001886 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001888 if (adev->adm_deregister_stream)
1889 adev->adm_deregister_stream(adev->adm_data, out->handle);
1890
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001891 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001893 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001894 if (out->pcm) {
1895 pcm_close(out->pcm);
1896 out->pcm = NULL;
1897 }
1898 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001899 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001900 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301901 out->send_next_track_params = false;
1902 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001903 out->gapless_mdata.encoder_delay = 0;
1904 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001905 if (out->compr != NULL) {
1906 compress_close(out->compr);
1907 out->compr = NULL;
1908 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001909 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001911 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 }
1913 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001914 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 return 0;
1916}
1917
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001918static int out_dump(const struct audio_stream *stream __unused,
1919 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920{
1921 return 0;
1922}
1923
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001924static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1925{
1926 int ret = 0;
1927 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001928
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001929 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001930 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931 return -EINVAL;
1932 }
1933
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301934 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001935
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1937 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301938 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001939 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001940 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1941 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301942 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001943 }
1944
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001945 ALOGV("%s new encoder delay %u and padding %u", __func__,
1946 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1947
1948 return 0;
1949}
1950
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001951static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1952{
1953 return out == adev->primary_output || out == adev->voice_tx_output;
1954}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1957{
1958 struct stream_out *out = (struct stream_out *)stream;
1959 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001960 struct audio_usecase *usecase;
1961 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 struct str_parms *parms;
1963 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001964 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001965 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966
sangwoobc677242013-08-08 16:53:43 +09001967 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001968 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301970 if (!parms)
1971 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001972 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1973 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001975 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001976 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001978 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301979 * When HDMI cable is unplugged/usb hs is disconnected the
1980 * music playback is paused and the policy manager sends routing=0
1981 * But the audioflingercontinues to write data until standby time
1982 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001983 * Avoid this by routing audio to speaker until standby.
1984 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301985 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1986 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001987 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001988 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1989 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001990 }
1991
1992 /*
1993 * select_devices() call below switches all the usecases on the same
1994 * backend to the new device. Refer to check_usecases_codec_backend() in
1995 * the select_devices(). But how do we undo this?
1996 *
1997 * For example, music playback is active on headset (deep-buffer usecase)
1998 * and if we go to ringtones and select a ringtone, low-latency usecase
1999 * will be started on headset+speaker. As we can't enable headset+speaker
2000 * and headset devices at the same time, select_devices() switches the music
2001 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2002 * So when the ringtone playback is completed, how do we undo the same?
2003 *
2004 * We are relying on the out_set_parameters() call on deep-buffer output,
2005 * once the ringtone playback is ended.
2006 * NOTE: We should not check if the current devices are same as new devices.
2007 * Because select_devices() must be called to switch back the music
2008 * playback to headset.
2009 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002010 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002011 out->devices = val;
2012
2013 if (!out->standby)
2014 select_devices(adev, out->usecase);
2015
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002016 if (output_drives_call(adev, out)) {
2017 if(!voice_is_in_call(adev)) {
2018 if (adev->mode == AUDIO_MODE_IN_CALL) {
2019 adev->current_call_output = out;
2020 ret = voice_start_call(adev);
2021 }
2022 } else {
2023 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002024 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002025 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002026 }
2027 }
2028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002030 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002032
2033 if (out == adev->primary_output) {
2034 pthread_mutex_lock(&adev->lock);
2035 audio_extn_set_parameters(adev, parms);
2036 pthread_mutex_unlock(&adev->lock);
2037 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002038 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002039 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002040 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002041
2042 audio_extn_dts_create_state_notifier_node(out->usecase);
2043 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2044 popcount(out->channel_mask),
2045 out->playback_started);
2046
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002047 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002048 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302051error:
Eric Laurent994a6932013-07-17 11:51:42 -07002052 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 return ret;
2054}
2055
2056static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2057{
2058 struct stream_out *out = (struct stream_out *)stream;
2059 struct str_parms *query = str_parms_create_str(keys);
2060 char *str;
2061 char value[256];
2062 struct str_parms *reply = str_parms_create();
2063 size_t i, j;
2064 int ret;
2065 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002066
2067 if (!query || !reply) {
2068 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2069 return NULL;
2070 }
2071
Eric Laurent994a6932013-07-17 11:51:42 -07002072 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2074 if (ret >= 0) {
2075 value[0] = '\0';
2076 i = 0;
2077 while (out->supported_channel_masks[i] != 0) {
2078 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2079 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2080 if (!first) {
2081 strcat(value, "|");
2082 }
2083 strcat(value, out_channels_name_to_enum_table[j].name);
2084 first = false;
2085 break;
2086 }
2087 }
2088 i++;
2089 }
2090 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2091 str = str_parms_to_str(reply);
2092 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002093 voice_extn_out_get_parameters(out, query, reply);
2094 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002095 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002096 free(str);
2097 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002098 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002100
2101 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2102 if (ret >= 0) {
2103 value[0] = '\0';
2104 i = 0;
2105 first = true;
2106 while (out->supported_formats[i] != 0) {
2107 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2108 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2109 if (!first) {
2110 strcat(value, "|");
2111 }
2112 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2113 first = false;
2114 break;
2115 }
2116 }
2117 i++;
2118 }
2119 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2120 str = str_parms_to_str(reply);
2121 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 str_parms_destroy(query);
2123 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002124 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 return str;
2126}
2127
2128static uint32_t out_get_latency(const struct audio_stream_out *stream)
2129{
2130 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002131 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132
Alexy Josephaa54c872014-12-03 02:46:47 -08002133 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002134 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002135 } else {
2136 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002138 }
2139
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302140 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002141 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142}
2143
2144static int out_set_volume(struct audio_stream_out *stream, float left,
2145 float right)
2146{
Eric Laurenta9024de2013-04-04 09:19:12 -07002147 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148 int volume[2];
2149
Eric Laurenta9024de2013-04-04 09:19:12 -07002150 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2151 /* only take left channel into account: the API is for stereo anyway */
2152 out->muted = (left == 0.0f);
2153 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002154 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002155 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2156 /*
2157 * Set mute or umute on HDMI passthrough stream.
2158 * Only take left channel into account.
2159 * Mute is 0 and unmute 1
2160 */
2161 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2162 } else {
2163 char mixer_ctl_name[128];
2164 struct audio_device *adev = out->dev;
2165 struct mixer_ctl *ctl;
2166 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002167 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002169 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2170 "Compress Playback %d Volume", pcm_device_id);
2171 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2172 if (!ctl) {
2173 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2174 __func__, mixer_ctl_name);
2175 return -EINVAL;
2176 }
2177 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2178 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2179 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2180 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002182 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 return -ENOSYS;
2185}
2186
2187static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2188 size_t bytes)
2189{
2190 struct stream_out *out = (struct stream_out *)stream;
2191 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302192 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002193 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002195 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302196
Naresh Tanniru80659832014-06-04 18:17:56 +05302197 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002198 // increase written size during SSR to avoid mismatch
2199 // with the written frames count in AF
2200 if (!is_offload_usecase(out->usecase))
2201 out->written += bytes / (out->config.channels * sizeof(short));
2202
Naresh Tanniru80659832014-06-04 18:17:56 +05302203 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302204 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302205 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302206 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002207 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302208 //during SSR for compress usecase we should return error to flinger
2209 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2210 pthread_mutex_unlock(&out->lock);
2211 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302212 }
2213 }
2214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002216 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002217 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002218 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2219 ret = voice_extn_compress_voip_start_output_stream(out);
2220 else
2221 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002222 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002225 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 goto exit;
2227 }
vivek mehta446c3962015-09-14 10:57:35 -07002228 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002229 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231
Ashish Jain81eb2a82015-05-13 10:52:34 +05302232 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2233 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2234 adev->is_channel_status_set = true;
2235 }
2236
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002237 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002238 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002239 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002240 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002241 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2242 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302243 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2244 ALOGD("copl(%p):send next track params in gapless", out);
2245 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2246 out->send_next_track_params = false;
2247 out->is_compr_metadata_avail = false;
2248 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002249 }
2250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002251 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302252 if (ret < 0)
2253 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002254 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002255 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302256 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002257 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302258 } else if (-ENETRESET == ret) {
2259 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2260 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2261 pthread_mutex_unlock(&out->lock);
2262 out_standby(&out->stream.common);
2263 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302265 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002267 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 out->playback_started = 1;
2269 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002270
2271 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2272 popcount(out->channel_mask),
2273 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274 }
2275 pthread_mutex_unlock(&out->lock);
2276 return ret;
2277 } else {
2278 if (out->pcm) {
2279 if (out->muted)
2280 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002283
2284 if (adev->adm_request_focus)
2285 adev->adm_request_focus(adev->adm_data, out->handle);
2286
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002287 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2288 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2289 else
2290 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002291
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302292 if (ret < 0)
2293 ret = -errno;
2294 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002295 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002296
2297 if (adev->adm_abandon_focus)
2298 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 }
2301
2302exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302303 /* ToDo: There may be a corner case when SSR happens back to back during
2304 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302305 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302306 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302307 }
2308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 pthread_mutex_unlock(&out->lock);
2310
2311 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002312 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002313 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302314 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302315 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302316 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302317 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302318 out->standby = true;
2319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002321 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302322 out_get_sample_rate(&out->stream.common));
2323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 }
2325 return bytes;
2326}
2327
2328static int out_get_render_position(const struct audio_stream_out *stream,
2329 uint32_t *dsp_frames)
2330{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302332 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002333
2334 if (dsp_frames == NULL)
2335 return -EINVAL;
2336
2337 *dsp_frames = 0;
2338 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002339 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002340 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302342 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302344 if (ret < 0)
2345 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 ALOGVV("%s rendered frames %d sample_rate %d",
2347 __func__, *dsp_frames, out->sample_rate);
2348 }
2349 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302350 if (-ENETRESET == ret) {
2351 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2352 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2353 return -EINVAL;
2354 } else if(ret < 0) {
2355 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2356 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302357 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2358 /*
2359 * Handle corner case where compress session is closed during SSR
2360 * and timestamp is queried
2361 */
2362 ALOGE(" ERROR: sound card not active, return error");
2363 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302364 } else {
2365 return 0;
2366 }
Zhou Song32a556e2015-05-05 10:46:56 +08002367 } else if (audio_is_linear_pcm(out->format)) {
2368 *dsp_frames = out->written;
2369 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 } else
2371 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372}
2373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002374static int out_add_audio_effect(const struct audio_stream *stream __unused,
2375 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376{
2377 return 0;
2378}
2379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002380static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2381 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382{
2383 return 0;
2384}
2385
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002386static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2387 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388{
2389 return -EINVAL;
2390}
2391
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002392static int out_get_presentation_position(const struct audio_stream_out *stream,
2393 uint64_t *frames, struct timespec *timestamp)
2394{
2395 struct stream_out *out = (struct stream_out *)stream;
2396 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002397 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002398
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002399 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002400
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002401 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002402 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302403 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002404 &out->sample_rate);
2405 ALOGVV("%s rendered frames %ld sample_rate %d",
2406 __func__, dsp_frames, out->sample_rate);
2407 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302408 if (ret < 0)
2409 ret = -errno;
2410 if (-ENETRESET == ret) {
2411 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2412 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2413 ret = -EINVAL;
2414 } else
2415 ret = 0;
2416
Eric Laurent949a0892013-09-20 09:20:13 -07002417 /* this is the best we can do */
2418 clock_gettime(CLOCK_MONOTONIC, timestamp);
2419 }
2420 } else {
2421 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002422 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002423 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2424 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002425 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002426 // This adjustment accounts for buffering after app processor.
2427 // It is based on estimated DSP latency per use case, rather than exact.
2428 signed_frames -=
2429 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2430
Eric Laurent949a0892013-09-20 09:20:13 -07002431 // It would be unusual for this value to be negative, but check just in case ...
2432 if (signed_frames >= 0) {
2433 *frames = signed_frames;
2434 ret = 0;
2435 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002436 }
2437 }
2438 }
2439
2440 pthread_mutex_unlock(&out->lock);
2441
2442 return ret;
2443}
2444
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445static int out_set_callback(struct audio_stream_out *stream,
2446 stream_callback_t callback, void *cookie)
2447{
2448 struct stream_out *out = (struct stream_out *)stream;
2449
2450 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002451 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 out->offload_callback = callback;
2453 out->offload_cookie = cookie;
2454 pthread_mutex_unlock(&out->lock);
2455 return 0;
2456}
2457
2458static int out_pause(struct audio_stream_out* stream)
2459{
2460 struct stream_out *out = (struct stream_out *)stream;
2461 int status = -ENOSYS;
2462 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002463 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002464 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302467 struct audio_device *adev = out->dev;
2468 int snd_scard_state = get_snd_card_state(adev);
2469
2470 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2471 status = compress_pause(out->compr);
2472
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002474
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302475 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002476 audio_extn_dts_notify_playback_state(out->usecase, 0,
2477 out->sample_rate, popcount(out->channel_mask),
2478 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002479 }
2480 pthread_mutex_unlock(&out->lock);
2481 }
2482 return status;
2483}
2484
2485static int out_resume(struct audio_stream_out* stream)
2486{
2487 struct stream_out *out = (struct stream_out *)stream;
2488 int status = -ENOSYS;
2489 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002490 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002491 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002492 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002493 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302495 struct audio_device *adev = out->dev;
2496 int snd_scard_state = get_snd_card_state(adev);
2497
2498 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2499 status = compress_resume(out->compr);
2500
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002501 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002502
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302503 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002504 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2505 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 }
2507 pthread_mutex_unlock(&out->lock);
2508 }
2509 return status;
2510}
2511
2512static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2513{
2514 struct stream_out *out = (struct stream_out *)stream;
2515 int status = -ENOSYS;
2516 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002517 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002518 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2520 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2521 else
2522 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2523 pthread_mutex_unlock(&out->lock);
2524 }
2525 return status;
2526}
2527
2528static int out_flush(struct audio_stream_out* stream)
2529{
2530 struct stream_out *out = (struct stream_out *)stream;
2531 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002532 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002533 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002534 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 stop_compressed_output_l(out);
2536 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002537 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002538 return 0;
2539 }
2540 return -ENOSYS;
2541}
2542
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543/** audio_stream_in implementation **/
2544static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2545{
2546 struct stream_in *in = (struct stream_in *)stream;
2547
2548 return in->config.rate;
2549}
2550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002551static int in_set_sample_rate(struct audio_stream *stream __unused,
2552 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553{
2554 return -ENOSYS;
2555}
2556
2557static size_t in_get_buffer_size(const struct audio_stream *stream)
2558{
2559 struct stream_in *in = (struct stream_in *)stream;
2560
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002561 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2562 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002563 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2564 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002565
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002566 return in->config.period_size *
2567 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568}
2569
2570static uint32_t in_get_channels(const struct audio_stream *stream)
2571{
2572 struct stream_in *in = (struct stream_in *)stream;
2573
2574 return in->channel_mask;
2575}
2576
2577static audio_format_t in_get_format(const struct audio_stream *stream)
2578{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002579 struct stream_in *in = (struct stream_in *)stream;
2580
2581 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582}
2583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002584static int in_set_format(struct audio_stream *stream __unused,
2585 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586{
2587 return -ENOSYS;
2588}
2589
2590static int in_standby(struct audio_stream *stream)
2591{
2592 struct stream_in *in = (struct stream_in *)stream;
2593 struct audio_device *adev = in->dev;
2594 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302595 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2596 stream, in->usecase, use_case_table[in->usecase]);
2597
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002598 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2599 /* Ignore standby in case of voip call because the voip input
2600 * stream is closed in adev_close_input_stream()
2601 */
2602 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2603 return status;
2604 }
2605
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002606 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002607 if (!in->standby && in->is_st_session) {
2608 ALOGD("%s: sound trigger pcm stop lab", __func__);
2609 audio_extn_sound_trigger_stop_lab(in);
2610 in->standby = 1;
2611 }
2612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002614 if (adev->adm_deregister_stream)
2615 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2616
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002617 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002619 if (in->pcm) {
2620 pcm_close(in->pcm);
2621 in->pcm = NULL;
2622 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002624 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 }
2626 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002627 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 return status;
2629}
2630
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002631static int in_dump(const struct audio_stream *stream __unused,
2632 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633{
2634 return 0;
2635}
2636
2637static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2638{
2639 struct stream_in *in = (struct stream_in *)stream;
2640 struct audio_device *adev = in->dev;
2641 struct str_parms *parms;
2642 char *str;
2643 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002644 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302646 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 parms = str_parms_create_str(kvpairs);
2648
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302649 if (!parms)
2650 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002651 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002652 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002653
2654 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2655 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 val = atoi(value);
2657 /* no audio source uses val == 0 */
2658 if ((in->source != val) && (val != 0)) {
2659 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002660 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2661 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2662 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2663 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002664 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002665 err = voice_extn_compress_voip_open_input_stream(in);
2666 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002667 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002668 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002669 }
2670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672 }
2673
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002674 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2675 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002677 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 in->device = val;
2679 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002680 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682 }
2683 }
2684
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002685done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002687 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688
2689 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302690error:
Eric Laurent994a6932013-07-17 11:51:42 -07002691 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 return ret;
2693}
2694
2695static char* in_get_parameters(const struct audio_stream *stream,
2696 const char *keys)
2697{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002698 struct stream_in *in = (struct stream_in *)stream;
2699 struct str_parms *query = str_parms_create_str(keys);
2700 char *str;
2701 char value[256];
2702 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002703
2704 if (!query || !reply) {
2705 ALOGE("in_get_parameters: failed to create query or reply");
2706 return NULL;
2707 }
2708
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002709 ALOGV("%s: enter: keys - %s", __func__, keys);
2710
2711 voice_extn_in_get_parameters(in, query, reply);
2712
2713 str = str_parms_to_str(reply);
2714 str_parms_destroy(query);
2715 str_parms_destroy(reply);
2716
2717 ALOGV("%s: exit: returns - %s", __func__, str);
2718 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719}
2720
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002721static int in_set_gain(struct audio_stream_in *stream __unused,
2722 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723{
2724 return 0;
2725}
2726
2727static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2728 size_t bytes)
2729{
2730 struct stream_in *in = (struct stream_in *)stream;
2731 struct audio_device *adev = in->dev;
2732 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302733 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002735 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302736
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002737 if (in->is_st_session) {
2738 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2739 /* Read from sound trigger HAL */
2740 audio_extn_sound_trigger_read(in, buffer, bytes);
2741 pthread_mutex_unlock(&in->lock);
2742 return bytes;
2743 }
2744
2745 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2746 ALOGD(" %s: sound card is not active/SSR state", __func__);
2747 ret= -EIO;;
2748 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302749 }
2750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002752 pthread_mutex_lock(&adev->lock);
2753 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2754 ret = voice_extn_compress_voip_start_input_stream(in);
2755 else
2756 ret = start_input_stream(in);
2757 pthread_mutex_unlock(&adev->lock);
2758 if (ret != 0) {
2759 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 }
2761 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002762 if (adev->adm_register_input_stream)
2763 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002766 if (adev->adm_request_focus)
2767 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002770 if (audio_extn_ssr_get_enabled() &&
2771 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002772 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002773 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2774 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002775 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2776 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002777 else
2778 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302779 if (ret < 0)
2780 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 }
2782
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002783 if (adev->adm_abandon_focus)
2784 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 /*
2787 * Instead of writing zeroes here, we could trust the hardware
2788 * to always provide zeroes when muted.
2789 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302790 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2791 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 memset(buffer, 0, bytes);
2793
2794exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302795 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302796 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002797 if (-ENETRESET == ret)
2798 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 pthread_mutex_unlock(&in->lock);
2801
2802 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302803 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302804 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302805 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302806 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302807 in->standby = true;
2808 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302809 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002811 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002812 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302813 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 }
2815 return bytes;
2816}
2817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002818static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819{
2820 return 0;
2821}
2822
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002823static int add_remove_audio_effect(const struct audio_stream *stream,
2824 effect_handle_t effect,
2825 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002827 struct stream_in *in = (struct stream_in *)stream;
2828 int status = 0;
2829 effect_descriptor_t desc;
2830
2831 status = (*effect)->get_descriptor(effect, &desc);
2832 if (status != 0)
2833 return status;
2834
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002835 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002836 pthread_mutex_lock(&in->dev->lock);
2837 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2838 in->enable_aec != enable &&
2839 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2840 in->enable_aec = enable;
2841 if (!in->standby)
2842 select_devices(in->dev, in->usecase);
2843 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002844 if (in->enable_ns != enable &&
2845 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2846 in->enable_ns = enable;
2847 if (!in->standby)
2848 select_devices(in->dev, in->usecase);
2849 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002850 pthread_mutex_unlock(&in->dev->lock);
2851 pthread_mutex_unlock(&in->lock);
2852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 return 0;
2854}
2855
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002856static int in_add_audio_effect(const struct audio_stream *stream,
2857 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858{
Eric Laurent994a6932013-07-17 11:51:42 -07002859 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002860 return add_remove_audio_effect(stream, effect, true);
2861}
2862
2863static int in_remove_audio_effect(const struct audio_stream *stream,
2864 effect_handle_t effect)
2865{
Eric Laurent994a6932013-07-17 11:51:42 -07002866 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002867 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868}
2869
2870static int adev_open_output_stream(struct audio_hw_device *dev,
2871 audio_io_handle_t handle,
2872 audio_devices_t devices,
2873 audio_output_flags_t flags,
2874 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002875 struct audio_stream_out **stream_out,
2876 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877{
2878 struct audio_device *adev = (struct audio_device *)dev;
2879 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002880 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002881 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302884
2885 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2886 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002887 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302888 return -EINVAL;
2889 }
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2892
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302893 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2894 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2895 devices, flags, &out->stream);
2896
2897
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002898 if (!out) {
2899 return -ENOMEM;
2900 }
2901
Haynes Mathew George204045b2015-02-25 20:32:03 -08002902 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002903 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002904 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 if (devices == AUDIO_DEVICE_NONE)
2907 devices = AUDIO_DEVICE_OUT_SPEAKER;
2908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 out->flags = flags;
2910 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002911 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002912 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 out->sample_rate = config->sample_rate;
2914 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2915 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002916 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002918 out->non_blocking = 0;
2919 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920
2921 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002922 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2923 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002924 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2925 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2926
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002927 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002928 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2929 ret = read_hdmi_channel_masks(out);
2930
2931 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2932 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002933 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002934 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002935 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002936
2937 if (config->sample_rate == 0)
2938 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2939 if (config->channel_mask == 0)
2940 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2941
2942 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2945 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002947 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002949 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2950 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002951 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002952 ret = voice_extn_compress_voip_open_output_stream(out);
2953 if (ret != 0) {
2954 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2955 __func__, ret);
2956 goto error_open;
2957 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002958 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2959 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2960
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002961 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2962 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2963 ALOGE("%s: Unsupported Offload information", __func__);
2964 ret = -EINVAL;
2965 goto error_open;
2966 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002967
2968 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2969 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2970 ALOGV("read and update_pass through formats");
2971 ret = audio_extn_dolby_update_passt_formats(adev, out);
2972 if(ret != 0) {
2973 goto error_open;
2974 }
2975 if(config->offload_info.format == 0)
2976 config->offload_info.format = out->supported_formats[0];
2977 }
2978
Mingming Yin90310102013-11-13 16:57:00 -08002979 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002980 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002981 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 ret = -EINVAL;
2983 goto error_open;
2984 }
2985
2986 out->compr_config.codec = (struct snd_codec *)
2987 calloc(1, sizeof(struct snd_codec));
2988
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002989 if (!out->compr_config.codec) {
2990 ret = -ENOMEM;
2991 goto error_open;
2992 }
2993
vivek mehta0ea887a2015-08-26 14:01:20 -07002994 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07002995 out->usecase = get_offload_usecase(adev, true);
2996 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07002997 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07002998 out->stream.set_callback = out_set_callback;
2999 out->stream.pause = out_pause;
3000 out->stream.resume = out_resume;
3001 out->stream.drain = out_drain;
3002 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003003 out->usecase = get_offload_usecase(adev, false);
3004 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003005 }
vivek mehta446c3962015-09-14 10:57:35 -07003006
3007 if (out->usecase == USECASE_INVALID) {
3008 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3009 ret = -EEXIST;
3010 goto error_open;
3011 }
3012
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003013 if (config->offload_info.channel_mask)
3014 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003015 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003016 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003017 config->offload_info.channel_mask = config->channel_mask;
3018 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003019 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 out->sample_rate = config->offload_info.sample_rate;
3021
Mingming Yin3ee55c62014-08-04 14:23:35 -07003022 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003023
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003024 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003025 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003026 audio_extn_dolby_get_snd_codec_id(adev, out,
3027 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003028 else
3029 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003031
3032 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3033 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003034 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003035 platform_get_pcm_offload_buffer_size(&config->offload_info);
3036 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3037 out->compr_config.fragment_size =
3038 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003039 } else {
3040 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003041 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003042 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3044 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003045 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 out->compr_config.codec->bit_rate =
3047 config->offload_info.bit_rate;
3048 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003049 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303051 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003052 /*TODO: Do we need to change it for passthrough */
3053 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054
Manish Dewangana6fc5442015-08-24 20:30:31 +05303055 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3056 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3057 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3058 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003059 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3060 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003061 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003062 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003063 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3064 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003065
Mingming Yin3ee55c62014-08-04 14:23:35 -07003066 if (out->bit_width == 24) {
3067 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3068 }
3069
Amit Shekhar6f461b12014-08-01 14:52:58 -07003070 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303071 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3074 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003075
Mingming Yin497419f2015-07-01 16:57:32 -07003076 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003077 //this flag is set from framework only if its for PCM formats
3078 //no need to check for PCM format again
3079 out->non_blocking = 0;
3080 out->use_small_bufs = true;
3081 ALOGI("Keep write blocking for small buff: non_blockling %d",
3082 out->non_blocking);
3083 }
3084
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003085 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303086 out->send_next_track_params = false;
3087 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003088 out->offload_state = OFFLOAD_STATE_IDLE;
3089 out->playback_started = 0;
3090
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003091 audio_extn_dts_create_state_notifier_node(out->usecase);
3092
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093 create_offload_callback_thread(out);
3094 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3095 __func__, config->offload_info.version,
3096 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003097 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003098 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003099 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3100 ret = voice_check_and_set_incall_music_usecase(adev, out);
3101 if (ret != 0) {
3102 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3103 __func__, ret);
3104 goto error_open;
3105 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003106 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3107 if (config->sample_rate == 0)
3108 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3109 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3110 config->sample_rate != 8000) {
3111 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3112 ret = -EINVAL;
3113 goto error_open;
3114 }
3115 out->sample_rate = config->sample_rate;
3116 out->config.rate = config->sample_rate;
3117 if (config->format == AUDIO_FORMAT_DEFAULT)
3118 config->format = AUDIO_FORMAT_PCM_16_BIT;
3119 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3120 config->format = AUDIO_FORMAT_PCM_16_BIT;
3121 ret = -EINVAL;
3122 goto error_open;
3123 }
3124 out->format = config->format;
3125 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3126 out->config = pcm_config_afe_proxy_playback;
3127 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003128 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3129 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3130 out->config = pcm_config_low_latency;
3131 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003132 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003133 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3135 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003137 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3138 format = AUDIO_FORMAT_PCM_16_BIT;
3139 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3140 out->config = pcm_config_deep_buffer;
3141 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003142 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003143 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003144 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003145 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003146 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003147 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 }
3149
Amit Shekhar1d896042014-10-03 13:16:09 -07003150 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3151 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003152 /* TODO remove this hardcoding and check why width is zero*/
3153 if (out->bit_width == 0)
3154 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003155 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3156 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003157 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003158 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003159 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3160 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3161 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003162 if(adev->primary_output == NULL)
3163 adev->primary_output = out;
3164 else {
3165 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003166 ret = -EEXIST;
3167 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003168 }
3169 }
3170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 /* Check if this usecase is already existing */
3172 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003173 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3174 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003177 ret = -EEXIST;
3178 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 }
3180 pthread_mutex_unlock(&adev->lock);
3181
3182 out->stream.common.get_sample_rate = out_get_sample_rate;
3183 out->stream.common.set_sample_rate = out_set_sample_rate;
3184 out->stream.common.get_buffer_size = out_get_buffer_size;
3185 out->stream.common.get_channels = out_get_channels;
3186 out->stream.common.get_format = out_get_format;
3187 out->stream.common.set_format = out_set_format;
3188 out->stream.common.standby = out_standby;
3189 out->stream.common.dump = out_dump;
3190 out->stream.common.set_parameters = out_set_parameters;
3191 out->stream.common.get_parameters = out_get_parameters;
3192 out->stream.common.add_audio_effect = out_add_audio_effect;
3193 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3194 out->stream.get_latency = out_get_latency;
3195 out->stream.set_volume = out_set_volume;
3196 out->stream.write = out_write;
3197 out->stream.get_render_position = out_get_render_position;
3198 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003199 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003202 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003203 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204
3205 config->format = out->stream.common.get_format(&out->stream.common);
3206 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3207 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3208
3209 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303210 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003211 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003212
3213 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3214 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3215 popcount(out->channel_mask), out->playback_started);
3216
Eric Laurent994a6932013-07-17 11:51:42 -07003217 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003219
3220error_open:
3221 free(out);
3222 *stream_out = NULL;
3223 ALOGD("%s: exit: ret %d", __func__, ret);
3224 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225}
3226
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003227static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 struct audio_stream_out *stream)
3229{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003230 struct stream_out *out = (struct stream_out *)stream;
3231 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003232 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003233
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303234 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3235
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003236 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303237 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003238 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303239 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003240 if(ret != 0)
3241 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3242 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003243 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003244 out_standby(&stream->common);
3245
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003246 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003247 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003249 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003250 if (out->compr_config.codec != NULL)
3251 free(out->compr_config.codec);
3252 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003253
3254 if (adev->voice_tx_output == out)
3255 adev->voice_tx_output = NULL;
3256
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 pthread_cond_destroy(&out->cond);
3258 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003260 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261}
3262
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003263static void close_compress_sessions(struct audio_device *adev)
3264{
Mingming Yin7b762e72015-03-04 13:47:32 -08003265 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303266 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003267 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003268 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303269
3270 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003271 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303272 if (is_offload_usecase(usecase->id)) {
3273 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003274 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3275 out = usecase->stream.out;
3276 pthread_mutex_unlock(&adev->lock);
3277 out_standby(&out->stream.common);
3278 pthread_mutex_lock(&adev->lock);
3279 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303280 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003281 }
3282 pthread_mutex_unlock(&adev->lock);
3283}
3284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3286{
3287 struct audio_device *adev = (struct audio_device *)dev;
3288 struct str_parms *parms;
3289 char *str;
3290 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003291 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003292 int ret;
3293 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003295 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303298 if (!parms)
3299 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003300 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3301 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303302 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303303 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303304 struct listnode *node;
3305 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303306 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303307 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003308 //close compress sessions on OFFLINE status
3309 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303310 } else if (strstr(snd_card_status, "ONLINE")) {
3311 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303312 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003313 //send dts hpx license if enabled
3314 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303315 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303316 }
3317
3318 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003319 status = voice_set_parameters(adev, parms);
3320 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003321 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003323 status = platform_set_parameters(adev->platform, parms);
3324 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003325 goto done;
3326
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003327 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3328 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003329 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3331 adev->bluetooth_nrec = true;
3332 else
3333 adev->bluetooth_nrec = false;
3334 }
3335
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003336 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3337 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3339 adev->screen_off = false;
3340 else
3341 adev->screen_off = true;
3342 }
3343
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003344 ret = str_parms_get_int(parms, "rotation", &val);
3345 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003346 bool reverse_speakers = false;
3347 switch(val) {
3348 // FIXME: note that the code below assumes that the speakers are in the correct placement
3349 // relative to the user when the device is rotated 90deg from its default rotation. This
3350 // assumption is device-specific, not platform-specific like this code.
3351 case 270:
3352 reverse_speakers = true;
3353 break;
3354 case 0:
3355 case 90:
3356 case 180:
3357 break;
3358 default:
3359 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003360 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003361 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003362 if (status == 0) {
3363 if (adev->speaker_lr_swap != reverse_speakers) {
3364 adev->speaker_lr_swap = reverse_speakers;
3365 // only update the selected device if there is active pcm playback
3366 struct audio_usecase *usecase;
3367 struct listnode *node;
3368 list_for_each(node, &adev->usecase_list) {
3369 usecase = node_to_item(node, struct audio_usecase, list);
3370 if (usecase->type == PCM_PLAYBACK) {
3371 select_devices(adev, usecase->id);
3372 break;
3373 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003374 }
3375 }
3376 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003377 }
3378
Mingming Yin514a8bc2014-07-29 15:22:21 -07003379 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3380 if (ret >= 0) {
3381 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3382 adev->bt_wb_speech_enabled = true;
3383 else
3384 adev->bt_wb_speech_enabled = false;
3385 }
3386
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003387 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3388 if (ret >= 0) {
3389 val = atoi(value);
3390 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3391 ALOGV("cache new edid");
3392 platform_cache_edid(adev->platform);
3393 }
3394 }
3395
3396 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3397 if (ret >= 0) {
3398 val = atoi(value);
3399 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3400 ALOGV("invalidate cached edid");
3401 platform_invalidate_edid(adev->platform);
3402 }
3403 }
3404
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003405 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003406
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003407done:
3408 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003409 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303410error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003411 ALOGV("%s: exit with code(%d)", __func__, status);
3412 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413}
3414
3415static char* adev_get_parameters(const struct audio_hw_device *dev,
3416 const char *keys)
3417{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003418 struct audio_device *adev = (struct audio_device *)dev;
3419 struct str_parms *reply = str_parms_create();
3420 struct str_parms *query = str_parms_create_str(keys);
3421 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303422 char value[256] = {0};
3423 int ret = 0;
3424
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003425 if (!query || !reply) {
3426 ALOGE("adev_get_parameters: failed to create query or reply");
3427 return NULL;
3428 }
3429
Naresh Tannirud7205b62014-06-20 02:54:48 +05303430 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3431 sizeof(value));
3432 if (ret >=0) {
3433 int val = 1;
3434 pthread_mutex_lock(&adev->snd_card_status.lock);
3435 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3436 val = 0;
3437 pthread_mutex_unlock(&adev->snd_card_status.lock);
3438 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3439 goto exit;
3440 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003441
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003442 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003443 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003444 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003445 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303446 pthread_mutex_unlock(&adev->lock);
3447
Naresh Tannirud7205b62014-06-20 02:54:48 +05303448exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003449 str = str_parms_to_str(reply);
3450 str_parms_destroy(query);
3451 str_parms_destroy(reply);
3452
3453 ALOGV("%s: exit: returns - %s", __func__, str);
3454 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455}
3456
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003457static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458{
3459 return 0;
3460}
3461
3462static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3463{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003464 int ret;
3465 struct audio_device *adev = (struct audio_device *)dev;
3466 pthread_mutex_lock(&adev->lock);
3467 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003468 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003469 pthread_mutex_unlock(&adev->lock);
3470 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471}
3472
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003473static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3474 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475{
3476 return -ENOSYS;
3477}
3478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003479static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3480 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481{
3482 return -ENOSYS;
3483}
3484
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003485static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3486 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487{
3488 return -ENOSYS;
3489}
3490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003491static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3492 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493{
3494 return -ENOSYS;
3495}
3496
3497static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3498{
3499 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 pthread_mutex_lock(&adev->lock);
3502 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003503 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003505 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3506 voice_is_in_call(adev)) {
3507 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003508 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003509 adev->current_call_output = NULL;
3510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 }
3512 pthread_mutex_unlock(&adev->lock);
3513 return 0;
3514}
3515
3516static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3517{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003518 int ret;
3519
3520 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003521 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003522 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3523 pthread_mutex_unlock(&adev->lock);
3524
3525 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526}
3527
3528static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3529{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003530 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 return 0;
3532}
3533
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003534static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 const struct audio_config *config)
3536{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003537 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003539 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3540 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541}
3542
3543static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003544 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 audio_devices_t devices,
3546 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003547 struct audio_stream_in **stream_in,
3548 audio_input_flags_t flags __unused,
3549 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003550 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551{
3552 struct audio_device *adev = (struct audio_device *)dev;
3553 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003554 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003555 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003556 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 *stream_in = NULL;
3559 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3560 return -EINVAL;
3561
3562 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003563
3564 if (!in) {
3565 ALOGE("failed to allocate input stream");
3566 return -ENOMEM;
3567 }
3568
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303569 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003570 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3571 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003573 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003574 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 in->stream.common.get_sample_rate = in_get_sample_rate;
3577 in->stream.common.set_sample_rate = in_set_sample_rate;
3578 in->stream.common.get_buffer_size = in_get_buffer_size;
3579 in->stream.common.get_channels = in_get_channels;
3580 in->stream.common.get_format = in_get_format;
3581 in->stream.common.set_format = in_set_format;
3582 in->stream.common.standby = in_standby;
3583 in->stream.common.dump = in_dump;
3584 in->stream.common.set_parameters = in_set_parameters;
3585 in->stream.common.get_parameters = in_get_parameters;
3586 in->stream.common.add_audio_effect = in_add_audio_effect;
3587 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3588 in->stream.set_gain = in_set_gain;
3589 in->stream.read = in_read;
3590 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3591
3592 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003593 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 in->standby = 1;
3596 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003597 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003598 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599
3600 /* Update config params with the requested sample rate and channels */
3601 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003602 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3603 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3604 is_low_latency = true;
3605#if LOW_LATENCY_CAPTURE_USE_CASE
3606 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3607#endif
3608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003611 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003613 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303614 if (adev->mode != AUDIO_MODE_IN_CALL) {
3615 ret = -EINVAL;
3616 goto err_open;
3617 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003618 if (config->sample_rate == 0)
3619 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3620 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3621 config->sample_rate != 8000) {
3622 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3623 ret = -EINVAL;
3624 goto err_open;
3625 }
3626 if (config->format == AUDIO_FORMAT_DEFAULT)
3627 config->format = AUDIO_FORMAT_PCM_16_BIT;
3628 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3629 config->format = AUDIO_FORMAT_PCM_16_BIT;
3630 ret = -EINVAL;
3631 goto err_open;
3632 }
3633
3634 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3635 in->config = pcm_config_afe_proxy_record;
3636 in->config.channels = channel_count;
3637 in->config.rate = config->sample_rate;
3638 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003639 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003640 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003641 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3642 ret = -EINVAL;
3643 goto err_open;
3644 }
3645 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003646 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003647 }
Mingming Yine62d7842013-10-25 16:26:03 -07003648 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003649 audio_extn_compr_cap_format_supported(config->format) &&
3650 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003651 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003652 } else {
3653 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003654 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003655 buffer_size = get_input_buffer_size(config->sample_rate,
3656 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003657 channel_count,
3658 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003659 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003660 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3661 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3662 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3663 (in->config.rate == 8000 || in->config.rate == 16000) &&
3664 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3665 voice_extn_compress_voip_open_input_stream(in);
3666 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003669 /* This stream could be for sound trigger lab,
3670 get sound trigger pcm if present */
3671 audio_extn_sound_trigger_check_and_get_session(in);
3672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003674 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003675 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676
3677err_open:
3678 free(in);
3679 *stream_in = NULL;
3680 return ret;
3681}
3682
3683static void adev_close_input_stream(struct audio_hw_device *dev,
3684 struct audio_stream_in *stream)
3685{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003686 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003687 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003688 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303689
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303690 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003691
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303692 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003693 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303694
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003695 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303696 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003697 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303698 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003699 if (ret != 0)
3700 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3701 __func__, ret);
3702 } else
3703 in_standby(&stream->common);
3704
Mingming Yin7b762e72015-03-04 13:47:32 -08003705 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003706 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003707 audio_extn_ssr_deinit();
3708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709
Mingming Yine62d7842013-10-25 16:26:03 -07003710 if(audio_extn_compr_cap_enabled() &&
3711 audio_extn_compr_cap_format_supported(in->config.format))
3712 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003713
3714 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 return;
3716}
3717
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003718static int adev_dump(const audio_hw_device_t *device __unused,
3719 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720{
3721 return 0;
3722}
3723
3724static int adev_close(hw_device_t *device)
3725{
3726 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003727
3728 if (!adev)
3729 return 0;
3730
3731 pthread_mutex_lock(&adev_init_lock);
3732
3733 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003734 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003735 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003736 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003737 audio_route_free(adev->audio_route);
3738 free(adev->snd_dev_ref_cnt);
3739 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003740 if (adev->adm_deinit)
3741 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003742 free(device);
3743 adev = NULL;
3744 }
3745 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 return 0;
3748}
3749
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003750/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3751 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3752 * just that it _might_ work.
3753 */
3754static int period_size_is_plausible_for_low_latency(int period_size)
3755{
3756 switch (period_size) {
3757 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003758 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003759 case 240:
3760 case 320:
3761 case 480:
3762 return 1;
3763 default:
3764 return 0;
3765 }
3766}
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768static int adev_open(const hw_module_t *module, const char *name,
3769 hw_device_t **device)
3770{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003771 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003773 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3775
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003776 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003777 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003778 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003779 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003780 ALOGD("%s: returning existing instance of adev", __func__);
3781 ALOGD("%s: exit", __func__);
3782 pthread_mutex_unlock(&adev_init_lock);
3783 return 0;
3784 }
3785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786 adev = calloc(1, sizeof(struct audio_device));
3787
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003788 if (!adev) {
3789 pthread_mutex_unlock(&adev_init_lock);
3790 return -ENOMEM;
3791 }
3792
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003793 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3796 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3797 adev->device.common.module = (struct hw_module_t *)module;
3798 adev->device.common.close = adev_close;
3799
3800 adev->device.init_check = adev_init_check;
3801 adev->device.set_voice_volume = adev_set_voice_volume;
3802 adev->device.set_master_volume = adev_set_master_volume;
3803 adev->device.get_master_volume = adev_get_master_volume;
3804 adev->device.set_master_mute = adev_set_master_mute;
3805 adev->device.get_master_mute = adev_get_master_mute;
3806 adev->device.set_mode = adev_set_mode;
3807 adev->device.set_mic_mute = adev_set_mic_mute;
3808 adev->device.get_mic_mute = adev_get_mic_mute;
3809 adev->device.set_parameters = adev_set_parameters;
3810 adev->device.get_parameters = adev_get_parameters;
3811 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3812 adev->device.open_output_stream = adev_open_output_stream;
3813 adev->device.close_output_stream = adev_close_output_stream;
3814 adev->device.open_input_stream = adev_open_input_stream;
3815 adev->device.close_input_stream = adev_close_input_stream;
3816 adev->device.dump = adev_dump;
3817
3818 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003820 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003821 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003824 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003825 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003826 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003827 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003828 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003829 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003830 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303831 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303832 adev->perf_lock_opts[0] = 0x101;
3833 adev->perf_lock_opts[1] = 0x20E;
3834 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303835
3836 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3837 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003839 adev->platform = platform_init(adev);
3840 if (!adev->platform) {
3841 free(adev->snd_dev_ref_cnt);
3842 free(adev);
3843 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3844 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003845 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003846 return -EINVAL;
3847 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003848
Naresh Tanniru4c630392014-05-12 01:05:52 +05303849 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3850
Eric Laurentc4aef752013-09-12 17:45:53 -07003851 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3852 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3853 if (adev->visualizer_lib == NULL) {
3854 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3855 } else {
3856 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3857 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003858 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003859 "visualizer_hal_start_output");
3860 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003861 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003862 "visualizer_hal_stop_output");
3863 }
3864 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003865 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003866 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003867
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003868 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3869 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3870 if (adev->offload_effects_lib == NULL) {
3871 ALOGE("%s: DLOPEN failed for %s", __func__,
3872 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3873 } else {
3874 ALOGV("%s: DLOPEN successful for %s", __func__,
3875 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3876 adev->offload_effects_start_output =
3877 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3878 "offload_effects_bundle_hal_start_output");
3879 adev->offload_effects_stop_output =
3880 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3881 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003882 adev->offload_effects_set_hpx_state =
3883 (int (*)(bool))dlsym(adev->offload_effects_lib,
3884 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303885 adev->offload_effects_get_parameters =
3886 (void (*)(struct str_parms *, struct str_parms *))
3887 dlsym(adev->offload_effects_lib,
3888 "offload_effects_bundle_get_parameters");
3889 adev->offload_effects_set_parameters =
3890 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3891 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003892 }
3893 }
3894
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003895 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3896 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3897 if (adev->adm_lib == NULL) {
3898 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3899 } else {
3900 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3901 adev->adm_init = (adm_init_t)
3902 dlsym(adev->adm_lib, "adm_init");
3903 adev->adm_deinit = (adm_deinit_t)
3904 dlsym(adev->adm_lib, "adm_deinit");
3905 adev->adm_register_input_stream = (adm_register_input_stream_t)
3906 dlsym(adev->adm_lib, "adm_register_input_stream");
3907 adev->adm_register_output_stream = (adm_register_output_stream_t)
3908 dlsym(adev->adm_lib, "adm_register_output_stream");
3909 adev->adm_deregister_stream = (adm_deregister_stream_t)
3910 dlsym(adev->adm_lib, "adm_deregister_stream");
3911 adev->adm_request_focus = (adm_request_focus_t)
3912 dlsym(adev->adm_lib, "adm_request_focus");
3913 adev->adm_abandon_focus = (adm_abandon_focus_t)
3914 dlsym(adev->adm_lib, "adm_abandon_focus");
3915 }
3916 }
3917
Mingming Yin514a8bc2014-07-29 15:22:21 -07003918 adev->bt_wb_speech_enabled = false;
3919
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003920 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 *device = &adev->device.common;
3922
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003923 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3924 &adev->streams_output_cfg_list);
3925
Kiran Kandi910e1862013-10-29 13:29:42 -07003926 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003927
3928 char value[PROPERTY_VALUE_MAX];
3929 int trial;
3930 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3931 trial = atoi(value);
3932 if (period_size_is_plausible_for_low_latency(trial)) {
3933 pcm_config_low_latency.period_size = trial;
3934 pcm_config_low_latency.start_threshold = trial / 4;
3935 pcm_config_low_latency.avail_min = trial / 4;
3936 configured_low_latency_capture_period_size = trial;
3937 }
3938 }
3939 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3940 trial = atoi(value);
3941 if (period_size_is_plausible_for_low_latency(trial)) {
3942 configured_low_latency_capture_period_size = trial;
3943 }
3944 }
3945
vivek mehta446c3962015-09-14 10:57:35 -07003946 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003947 pthread_mutex_unlock(&adev_init_lock);
3948
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003949 if (adev->adm_init)
3950 adev->adm_data = adev->adm_init();
3951
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303952 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07003953 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 return 0;
3955}
3956
3957static struct hw_module_methods_t hal_module_methods = {
3958 .open = adev_open,
3959};
3960
3961struct audio_module HAL_MODULE_INFO_SYM = {
3962 .common = {
3963 .tag = HARDWARE_MODULE_TAG,
3964 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3965 .hal_api_version = HARDWARE_HAL_API_VERSION,
3966 .id = AUDIO_HARDWARE_MODULE_ID,
3967 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003968 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 .methods = &hal_module_methods,
3970 },
3971};