blob: 1c1148472ce29ec65eb6d2c895dc7f537f7162ee [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",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700171#ifdef MULTIPLE_OFFLOAD_ENABLED
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
180#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700181 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
182
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,
217#ifdef MULTIPLE_OFFLOAD_ENABLED
218 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
219 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
vivek mehta0ea887a2015-08-26 14:01:20 -0700227 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700228};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229
230#define STRING_TO_ENUM(string) { #string, string }
231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800232struct string_to_enum {
233 const char *name;
234 uint32_t value;
235};
236
237static const struct string_to_enum out_channels_name_to_enum_table[] = {
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
245};
246
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700247static const struct string_to_enum out_formats_name_to_enum_table[] = {
248 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
250 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
251};
252
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700253static struct audio_device *adev = NULL;
254static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700255static unsigned int audio_device_ref_count;
256
Haynes Mathew George5191a852013-09-11 14:19:36 -0700257static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800258
vivek mehtaa76401a2015-04-24 14:12:15 -0700259__attribute__ ((visibility ("default")))
260bool audio_hw_send_gain_dep_calibration(int level) {
261 bool ret_val = false;
262 ALOGV("%s: called ... ", __func__);
263
264 pthread_mutex_lock(&adev_init_lock);
265
266 if (adev != NULL && adev->platform != NULL) {
267 pthread_mutex_lock(&adev->lock);
268 ret_val = platform_send_gain_dep_cal(adev->platform, level);
269 pthread_mutex_unlock(&adev->lock);
270 } else {
271 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
272 }
273
274 pthread_mutex_unlock(&adev_init_lock);
275
276 return ret_val;
277}
278
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800279static int check_and_set_gapless_mode(struct audio_device *adev) {
280
281
282 char value[PROPERTY_VALUE_MAX] = {0};
283 bool gapless_enabled = false;
284 const char *mixer_ctl_name = "Compress Gapless Playback";
285 struct mixer_ctl *ctl;
286
287 ALOGV("%s:", __func__);
288 property_get("audio.offload.gapless.enabled", value, NULL);
289 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
290
291 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
292 if (!ctl) {
293 ALOGE("%s: Could not get ctl for mixer cmd - %s",
294 __func__, mixer_ctl_name);
295 return -EINVAL;
296 }
297
298 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
299 ALOGE("%s: Could not set gapless mode %d",
300 __func__, gapless_enabled);
301 return -EINVAL;
302 }
303 return 0;
304}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306static bool is_supported_format(audio_format_t format)
307{
Eric Laurent86e17132013-09-12 17:49:30 -0700308 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 format == AUDIO_FORMAT_AAC_LC ||
310 format == AUDIO_FORMAT_AAC_HE_V1 ||
311 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530312 format == AUDIO_FORMAT_AAC_ADTS_LC ||
313 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
314 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800315 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700317 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800318 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530319 format == AUDIO_FORMAT_ALAC ||
320 format == AUDIO_FORMAT_APE ||
321 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800322 format == AUDIO_FORMAT_WMA ||
323 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800324 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700325
326 return false;
327}
328
329static int get_snd_codec_id(audio_format_t format)
330{
331 int id = 0;
332
Ashish Jainf9b78162014-08-25 20:36:25 +0530333 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700334 case AUDIO_FORMAT_MP3:
335 id = SND_AUDIOCODEC_MP3;
336 break;
337 case AUDIO_FORMAT_AAC:
338 id = SND_AUDIOCODEC_AAC;
339 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530340 case AUDIO_FORMAT_AAC_ADTS:
341 id = SND_AUDIOCODEC_AAC;
342 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530343 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700344 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800345 id = SND_AUDIOCODEC_PCM;
346 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700347 case AUDIO_FORMAT_FLAC:
348 id = SND_AUDIOCODEC_FLAC;
349 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530350 case AUDIO_FORMAT_ALAC:
351 id = SND_AUDIOCODEC_ALAC;
352 break;
353 case AUDIO_FORMAT_APE:
354 id = SND_AUDIOCODEC_APE;
355 break;
356 case AUDIO_FORMAT_VORBIS:
357 id = SND_AUDIOCODEC_VORBIS;
358 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800359 case AUDIO_FORMAT_WMA:
360 id = SND_AUDIOCODEC_WMA;
361 break;
362 case AUDIO_FORMAT_WMA_PRO:
363 id = SND_AUDIOCODEC_WMA_PRO;
364 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700365 default:
Mingming Yin90310102013-11-13 16:57:00 -0800366 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700367 }
368
369 return id;
370}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800371
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530372int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530373{
374 int snd_scard_state;
375
376 if (!adev)
377 return SND_CARD_STATE_OFFLINE;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
380 snd_scard_state = adev->snd_card_status.state;
381 pthread_mutex_unlock(&adev->snd_card_status.lock);
382
383 return snd_scard_state;
384}
385
386static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
387{
388 if (!adev)
389 return -ENOSYS;
390
391 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700392 if (adev->snd_card_status.state != snd_scard_state) {
393 adev->snd_card_status.state = snd_scard_state;
394 platform_snd_card_update(adev->platform, snd_scard_state);
395 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530396 pthread_mutex_unlock(&adev->snd_card_status.lock);
397
398 return 0;
399}
400
Avinash Vaish71a8b972014-07-24 15:36:33 +0530401static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
402 struct audio_usecase *uc_info)
403{
404 struct listnode *node;
405 struct audio_usecase *usecase;
406
407 if (uc_info == NULL)
408 return -EINVAL;
409
410 /* Re-route all voice usecases on the shared backend other than the
411 specified usecase to new snd devices */
412 list_for_each(node, &adev->usecase_list) {
413 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800414 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530415 enable_audio_route(adev, usecase);
416 }
417 return 0;
418}
419
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700420int pcm_ioctl(struct pcm *pcm, int request, ...)
421{
422 va_list ap;
423 void * arg;
424 int pcm_fd = *(int*)pcm;
425
426 va_start(ap, request);
427 arg = va_arg(ap, void *);
428 va_end(ap);
429
430 return ioctl(pcm_fd, request, arg);
431}
432
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700433int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700434 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700436 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700437 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438
439 if (usecase == NULL)
440 return -EINVAL;
441
442 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
443
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800444 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800448
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800449#ifdef DS1_DOLBY_DAP_ENABLED
450 audio_extn_dolby_set_dmid(adev);
451 audio_extn_dolby_set_endpoint(adev);
452#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700453 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700454 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530455 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700456 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530457 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800458 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700459 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700460 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700461 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462 ALOGV("%s: exit", __func__);
463 return 0;
464}
465
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700466int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700467 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800468{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700470 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800471
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530472 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800473 return -EINVAL;
474
475 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700476 if (usecase->type == PCM_CAPTURE)
477 snd_device = usecase->in_snd_device;
478 else
479 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800480 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700481 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700482 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700483 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700484 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530485 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800486 ALOGV("%s: exit", __func__);
487 return 0;
488}
489
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700490int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700491 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800492{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700493 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
494
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800495 if (snd_device < SND_DEVICE_MIN ||
496 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800497 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800498 return -EINVAL;
499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700500
501 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700502
503 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
504 ALOGE("%s: Invalid sound device returned", __func__);
505 return -EINVAL;
506 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700507 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700508 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700509 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700510 return 0;
511 }
512
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700513 if (audio_extn_spkr_prot_is_enabled())
514 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700515 /* start usb playback thread */
516 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
517 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
518 audio_extn_usb_start_playback(adev);
519
520 /* start usb capture thread */
521 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
522 audio_extn_usb_start_capture(adev);
523
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800524 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700525 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
526 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
527 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
528 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700529 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
530 adev->snd_dev_ref_cnt[snd_device]--;
531 return -EINVAL;
532 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200533 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800534 if (audio_extn_spkr_prot_start_processing(snd_device)) {
535 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200536 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800537 return -EINVAL;
538 }
539 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700540 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700541 /* due to the possibility of calibration overwrite between listen
542 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543 audio_extn_sound_trigger_update_device_status(snd_device,
544 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530545 audio_extn_listen_update_device_status(snd_device,
546 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700547 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700548 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700549 audio_extn_sound_trigger_update_device_status(snd_device,
550 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530551 audio_extn_listen_update_device_status(snd_device,
552 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700553 return -EINVAL;
554 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300555 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700556 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 return 0;
559}
560
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700561int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700562 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700564 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800566 if (snd_device < SND_DEVICE_MIN ||
567 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800568 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 return -EINVAL;
570 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
572 ALOGE("%s: device ref cnt is already 0", __func__);
573 return -EINVAL;
574 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700577
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
579 ALOGE("%s: Invalid sound device returned", __func__);
580 return -EINVAL;
581 }
582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700584 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800585 /* exit usb play back thread */
586 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
587 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
588 audio_extn_usb_stop_playback();
589
590 /* exit usb capture thread */
591 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700592 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800593
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800594 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700595 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
596 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
597 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200604 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700605 audio_extn_sound_trigger_update_device_status(snd_device,
606 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530607 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800608 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800611 return 0;
612}
613
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614static void check_usecases_codec_backend(struct audio_device *adev,
615 struct audio_usecase *uc_info,
616 snd_device_t snd_device)
617{
618 struct listnode *node;
619 struct audio_usecase *usecase;
620 bool switch_device[AUDIO_USECASE_MAX];
621 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800622 int backend_idx = DEFAULT_CODEC_BACKEND;
623 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700624
625 /*
626 * This function is to make sure that all the usecases that are active on
627 * the hardware codec backend are always routed to any one device that is
628 * handled by the hardware codec.
629 * For example, if low-latency and deep-buffer usecases are currently active
630 * on speaker and out_set_parameters(headset) is received on low-latency
631 * output, then we have to make sure deep-buffer is also switched to headset,
632 * because of the limitation that both the devices cannot be enabled
633 * at the same time as they share the same backend.
634 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700635 /*
636 * This call is to check if we need to force routing for a particular stream
637 * If there is a backend configuration change for the device when a
638 * new stream starts, then ADM needs to be closed and re-opened with the new
639 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800640 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700641 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800642 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
643 snd_device);
644 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800646 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800647 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 for (i = 0; i < AUDIO_USECASE_MAX; i++)
649 switch_device[i] = false;
650
651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653
654 if (usecase == uc_info)
655 continue;
656 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
657 ALOGV("%s: backend_idx: %d,"
658 "usecase_backend_idx: %d, curr device: %s, usecase device:"
659 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530660 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800661
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800662 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700663 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800664 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
665 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530666 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700668 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 switch_device[usecase->id] = true;
671 num_uc_to_switch++;
672 }
673 }
674
675 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700676 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530678 /* Make sure the previous devices to be disabled first and then enable the
679 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 list_for_each(node, &adev->usecase_list) {
681 usecase = node_to_item(node, struct audio_usecase, list);
682 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700683 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 }
685 }
686
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700687 list_for_each(node, &adev->usecase_list) {
688 usecase = node_to_item(node, struct audio_usecase, list);
689 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700690 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700691 }
692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 /* Re-route all the usecases on the shared backend other than the
695 specified usecase to new snd devices */
696 list_for_each(node, &adev->usecase_list) {
697 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530698 /* Update the out_snd_device only for the usecases that are enabled here */
699 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
700 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530701 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 }
703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 }
705}
706
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700707static void check_and_route_capture_usecases(struct audio_device *adev,
708 struct audio_usecase *uc_info,
709 snd_device_t snd_device)
710{
711 struct listnode *node;
712 struct audio_usecase *usecase;
713 bool switch_device[AUDIO_USECASE_MAX];
714 int i, num_uc_to_switch = 0;
715
716 /*
717 * This function is to make sure that all the active capture usecases
718 * are always routed to the same input sound device.
719 * For example, if audio-record and voice-call usecases are currently
720 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
721 * is received for voice call then we have to make sure that audio-record
722 * usecase is also switched to earpiece i.e. voice-dmic-ef,
723 * because of the limitation that two devices cannot be enabled
724 * at the same time if they share the same backend.
725 */
726 for (i = 0; i < AUDIO_USECASE_MAX; i++)
727 switch_device[i] = false;
728
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800731 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700733 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700734 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
735 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700736 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
738 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700739 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700741 switch_device[usecase->id] = true;
742 num_uc_to_switch++;
743 }
744 }
745
746 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700747 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530749 /* Make sure the previous devices to be disabled first and then enable the
750 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700751 list_for_each(node, &adev->usecase_list) {
752 usecase = node_to_item(node, struct audio_usecase, list);
753 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700754 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800755 }
756 }
757
758 list_for_each(node, &adev->usecase_list) {
759 usecase = node_to_item(node, struct audio_usecase, list);
760 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700761 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 }
763 }
764
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700765 /* Re-route all the usecases on the shared backend other than the
766 specified usecase to new snd devices */
767 list_for_each(node, &adev->usecase_list) {
768 usecase = node_to_item(node, struct audio_usecase, list);
769 /* Update the in_snd_device only before enabling the audio route */
770 if (switch_device[usecase->id] ) {
771 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800772 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530773 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 }
775 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 }
777}
778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700780static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700782 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700783 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784
785 switch (channels) {
786 /*
787 * Do not handle stereo output in Multi-channel cases
788 * Stereo case is handled in normal playback path
789 */
790 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700791 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 break;
798 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700799 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
801 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
804 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
805 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806 break;
807 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700808 ALOGE("HDMI does not support multi channel playback");
809 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810 break;
811 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700812 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813}
814
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800815audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
816 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700817{
818 struct audio_usecase *usecase;
819 struct listnode *node;
820
821 list_for_each(node, &adev->usecase_list) {
822 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800823 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700824 ALOGV("%s: usecase id %d", __func__, usecase->id);
825 return usecase->id;
826 }
827 }
828 return USECASE_INVALID;
829}
830
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700831struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700832 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833{
834 struct audio_usecase *usecase;
835 struct listnode *node;
836
837 list_for_each(node, &adev->usecase_list) {
838 usecase = node_to_item(node, struct audio_usecase, list);
839 if (usecase->id == uc_id)
840 return usecase;
841 }
842 return NULL;
843}
844
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700845int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800847 snd_device_t out_snd_device = SND_DEVICE_NONE;
848 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 struct audio_usecase *usecase = NULL;
850 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800851 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800852 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800853 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800854 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 usecase = get_usecase_from_list(adev, uc_id);
858 if (usecase == NULL) {
859 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
860 return -EINVAL;
861 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800863 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800864 (usecase->type == VOIP_CALL) ||
865 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800867 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 usecase->devices = usecase->stream.out->devices;
870 } else {
871 /*
872 * If the voice call is active, use the sound devices of voice call usecase
873 * so that it would not result any device switch. All the usecases will
874 * be switched to new device when select_devices() is called for voice call
875 * usecase. This is to avoid switching devices for voice call when
876 * check_usecases_codec_backend() is called below.
877 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700878 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700879 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800880 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700881 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
882 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 in_snd_device = vc_usecase->in_snd_device;
884 out_snd_device = vc_usecase->out_snd_device;
885 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800886 } else if (voice_extn_compress_voip_is_active(adev)) {
887 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700888 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530889 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700890 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800891 in_snd_device = voip_usecase->in_snd_device;
892 out_snd_device = voip_usecase->out_snd_device;
893 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800894 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800895 hfp_ucid = audio_extn_hfp_get_usecase();
896 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700897 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800898 in_snd_device = hfp_usecase->in_snd_device;
899 out_snd_device = hfp_usecase->out_snd_device;
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902 if (usecase->type == PCM_PLAYBACK) {
903 usecase->devices = usecase->stream.out->devices;
904 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700905 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700906 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800907 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700908 if (usecase->stream.out == adev->primary_output &&
909 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800910 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700911 select_devices(adev, adev->active_input->usecase);
912 }
913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914 } else if (usecase->type == PCM_CAPTURE) {
915 usecase->devices = usecase->stream.in->device;
916 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700917 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700918 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530919 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
920 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
921 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
922 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700923 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700924 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700925 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
926 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700927 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700928 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700929 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700930 }
931 }
932
933 if (out_snd_device == usecase->out_snd_device &&
934 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935 return 0;
936 }
937
sangwoobc677242013-08-08 16:53:43 +0900938 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700939 out_snd_device, platform_get_snd_device_name(out_snd_device),
940 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800942 /*
943 * Limitation: While in call, to do a device switch we need to disable
944 * and enable both RX and TX devices though one of them is same as current
945 * device.
946 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700947 if ((usecase->type == VOICE_CALL) &&
948 (usecase->in_snd_device != SND_DEVICE_NONE) &&
949 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700950 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700951 }
952
953 if (((usecase->type == VOICE_CALL) ||
954 (usecase->type == VOIP_CALL)) &&
955 (usecase->out_snd_device != SND_DEVICE_NONE)) {
956 /* Disable sidetone only if voice/voip call already exists */
957 if (voice_is_call_state_active(adev) ||
958 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700959 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800960 }
961
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 /* Disable current sound devices */
963 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 disable_audio_route(adev, usecase);
965 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 }
967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 disable_audio_route(adev, usecase);
970 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 }
972
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800973 /* Applicable only on the targets that has external modem.
974 * New device information should be sent to modem before enabling
975 * the devices to reduce in-call device switch time.
976 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700977 if ((usecase->type == VOICE_CALL) &&
978 (usecase->in_snd_device != SND_DEVICE_NONE) &&
979 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800980 status = platform_switch_voice_call_enable_device_config(adev->platform,
981 out_snd_device,
982 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700983 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 /* Enable new sound devices */
986 if (out_snd_device != SND_DEVICE_NONE) {
987 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
988 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700989 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 }
991
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 if (in_snd_device != SND_DEVICE_NONE) {
993 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700994 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700995 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700996
Avinash Vaish71a8b972014-07-24 15:36:33 +0530997 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700998 status = platform_switch_voice_call_device_post(adev->platform,
999 out_snd_device,
1000 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301001 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001002 /* Enable sidetone only if voice/voip call already exists */
1003 if (voice_is_call_state_active(adev) ||
1004 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001005 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301006 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001007
sangwoo170731f2013-06-08 15:36:36 +09001008 usecase->in_snd_device = in_snd_device;
1009 usecase->out_snd_device = out_snd_device;
1010
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301011 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001012 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001014 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301015 usecase->stream.out->flags,
1016 usecase->stream.out->format,
1017 usecase->stream.out->sample_rate,
1018 usecase->stream.out->bit_width,
1019 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001020 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301021 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001022
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001023 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001024
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001025 /* Applicable only on the targets that has external modem.
1026 * Enable device command should be sent to modem only after
1027 * enabling voice call mixer controls
1028 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001029 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001030 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1031 out_snd_device,
1032 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301033 ALOGD("%s: done",__func__);
1034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035 return status;
1036}
1037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038static int stop_input_stream(struct stream_in *in)
1039{
1040 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 struct audio_usecase *uc_info;
1042 struct audio_device *adev = in->dev;
1043
Eric Laurentc8400632013-02-14 19:04:54 -08001044 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045
Eric Laurent994a6932013-07-17 11:51:42 -07001046 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 uc_info = get_usecase_from_list(adev, in->usecase);
1049 if (uc_info == NULL) {
1050 ALOGE("%s: Could not find the usecase (%d) in the list",
1051 __func__, in->usecase);
1052 return -EINVAL;
1053 }
1054
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001055 /* Close in-call recording streams */
1056 voice_check_and_stop_incall_rec_usecase(adev, in);
1057
Eric Laurent150dbfe2013-02-27 14:31:02 -08001058 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060
1061 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001062 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001064 list_remove(&uc_info->list);
1065 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066
Eric Laurent994a6932013-07-17 11:51:42 -07001067 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 return ret;
1069}
1070
1071int start_input_stream(struct stream_in *in)
1072{
1073 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001074 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 struct audio_usecase *uc_info;
1076 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301077 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078
Mingming Yin2664a5b2015-09-03 10:53:11 -07001079 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1080 if (get_usecase_from_list(adev, usecase) == NULL)
1081 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301082 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1083 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001084
Naresh Tanniru80659832014-06-04 18:17:56 +05301085
1086 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301088 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089 goto error_config;
1090 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301091
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001092 /* Check if source matches incall recording usecase criteria */
1093 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1094 if (ret)
1095 goto error_config;
1096 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001097 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1098
1099 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1100 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1101 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1102 goto error_config;
1103 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001104
Eric Laurentb23d5282013-05-14 15:27:20 -07001105 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106 if (in->pcm_device_id < 0) {
1107 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1108 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001109 ret = -EINVAL;
1110 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112
1113 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001115
1116 if (!uc_info) {
1117 ret = -ENOMEM;
1118 goto error_config;
1119 }
1120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 uc_info->id = in->usecase;
1122 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001123 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 uc_info->devices = in->device;
1125 uc_info->in_snd_device = SND_DEVICE_NONE;
1126 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001128 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301129 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131
Eric Laurentc8400632013-02-14 19:04:54 -08001132 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001133 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1134
1135 unsigned int flags = PCM_IN;
1136 unsigned int pcm_open_retry_count = 0;
1137
1138 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1139 flags |= PCM_MMAP | PCM_NOIRQ;
1140 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1141 }
1142
1143 while (1) {
1144 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1145 flags, &in->config);
1146 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1147 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1148 if (in->pcm != NULL) {
1149 pcm_close(in->pcm);
1150 in->pcm = NULL;
1151 }
1152 if (pcm_open_retry_count-- == 0) {
1153 ret = -EIO;
1154 goto error_open;
1155 }
1156 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1157 continue;
1158 }
1159 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001160 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001161
1162 ALOGV("%s: pcm_prepare", __func__);
1163 ret = pcm_prepare(in->pcm);
1164 if (ret < 0) {
1165 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1166 pcm_close(in->pcm);
1167 in->pcm = NULL;
1168 goto error_open;
1169 }
1170
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301171 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301172
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001173 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001174
Eric Laurentc8400632013-02-14 19:04:54 -08001175 return ret;
1176
1177error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301179 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001180
1181error_config:
1182 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301183 /*
1184 * sleep 50ms to allow sufficient time for kernel
1185 * drivers to recover incases like SSR.
1186 */
1187 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001189
1190 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191}
1192
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001193/* must be called with out->lock locked */
1194static int send_offload_cmd_l(struct stream_out* out, int command)
1195{
1196 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1197
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001198 if (!cmd) {
1199 ALOGE("failed to allocate mem for command 0x%x", command);
1200 return -ENOMEM;
1201 }
1202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203 ALOGVV("%s %d", __func__, command);
1204
1205 cmd->cmd = command;
1206 list_add_tail(&out->offload_cmd_list, &cmd->node);
1207 pthread_cond_signal(&out->offload_cond);
1208 return 0;
1209}
1210
1211/* must be called iwth out->lock locked */
1212static void stop_compressed_output_l(struct stream_out *out)
1213{
1214 out->offload_state = OFFLOAD_STATE_IDLE;
1215 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001216 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 if (out->compr != NULL) {
1218 compress_stop(out->compr);
1219 while (out->offload_thread_blocked) {
1220 pthread_cond_wait(&out->cond, &out->lock);
1221 }
1222 }
1223}
1224
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001225bool is_offload_usecase(audio_usecase_t uc_id)
1226{
1227 unsigned int i;
1228 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1229 if (uc_id == offload_usecases[i])
1230 return true;
1231 }
1232 return false;
1233}
1234
1235static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1236{
1237 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1238 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1239 char value[PROPERTY_VALUE_MAX] = {0};
1240
1241 property_get("audio.offload.multiple.enabled", value, NULL);
1242 if (!(atoi(value) || !strncmp("true", value, 4)))
1243 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1244
1245 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1246 for (i = 0; i < num_usecase; i++) {
1247 if (!(adev->offload_usecases_state & (0x1<<i))) {
1248 adev->offload_usecases_state |= 0x1 << i;
1249 ret = offload_usecases[i];
1250 break;
1251 }
1252 }
1253 ALOGV("%s: offload usecase is %d", __func__, ret);
1254 return ret;
1255}
1256
1257static void free_offload_usecase(struct audio_device *adev,
1258 audio_usecase_t uc_id)
1259{
1260 unsigned int i;
1261 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1262 if (offload_usecases[i] == uc_id) {
1263 adev->offload_usecases_state &= ~(0x1<<i);
1264 break;
1265 }
1266 }
1267 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1268}
1269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001270static void *offload_thread_loop(void *context)
1271{
1272 struct stream_out *out = (struct stream_out *) context;
1273 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001274 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001275
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1277 set_sched_policy(0, SP_FOREGROUND);
1278 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1279
1280 ALOGV("%s", __func__);
1281 pthread_mutex_lock(&out->lock);
1282 for (;;) {
1283 struct offload_cmd *cmd = NULL;
1284 stream_callback_event_t event;
1285 bool send_callback = false;
1286
1287 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1288 __func__, list_empty(&out->offload_cmd_list),
1289 out->offload_state);
1290 if (list_empty(&out->offload_cmd_list)) {
1291 ALOGV("%s SLEEPING", __func__);
1292 pthread_cond_wait(&out->offload_cond, &out->lock);
1293 ALOGV("%s RUNNING", __func__);
1294 continue;
1295 }
1296
1297 item = list_head(&out->offload_cmd_list);
1298 cmd = node_to_item(item, struct offload_cmd, node);
1299 list_remove(item);
1300
1301 ALOGVV("%s STATE %d CMD %d out->compr %p",
1302 __func__, out->offload_state, cmd->cmd, out->compr);
1303
1304 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1305 free(cmd);
1306 break;
1307 }
1308
1309 if (out->compr == NULL) {
1310 ALOGE("%s: Compress handle is NULL", __func__);
1311 pthread_cond_signal(&out->cond);
1312 continue;
1313 }
1314 out->offload_thread_blocked = true;
1315 pthread_mutex_unlock(&out->lock);
1316 send_callback = false;
1317 switch(cmd->cmd) {
1318 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001319 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001321 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001322 send_callback = true;
1323 event = STREAM_CBK_EVENT_WRITE_READY;
1324 break;
1325 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001326 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301327 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001328 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301329 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001330 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301331 if (ret < 0)
1332 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301333 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301334 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001335 compress_drain(out->compr);
1336 else
1337 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301338 if (ret != -ENETRESET) {
1339 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301340 pthread_mutex_lock(&out->lock);
1341 out->send_new_metadata = 1;
1342 out->send_next_track_params = true;
1343 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301344 event = STREAM_CBK_EVENT_DRAIN_READY;
1345 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1346 } else
1347 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001348 break;
1349 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001350 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001351 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001352 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001353 send_callback = true;
1354 event = STREAM_CBK_EVENT_DRAIN_READY;
1355 break;
1356 default:
1357 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1358 break;
1359 }
1360 pthread_mutex_lock(&out->lock);
1361 out->offload_thread_blocked = false;
1362 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001363 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001364 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001365 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001366 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001367 free(cmd);
1368 }
1369
1370 pthread_cond_signal(&out->cond);
1371 while (!list_empty(&out->offload_cmd_list)) {
1372 item = list_head(&out->offload_cmd_list);
1373 list_remove(item);
1374 free(node_to_item(item, struct offload_cmd, node));
1375 }
1376 pthread_mutex_unlock(&out->lock);
1377
1378 return NULL;
1379}
1380
1381static int create_offload_callback_thread(struct stream_out *out)
1382{
1383 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1384 list_init(&out->offload_cmd_list);
1385 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1386 offload_thread_loop, out);
1387 return 0;
1388}
1389
1390static int destroy_offload_callback_thread(struct stream_out *out)
1391{
1392 pthread_mutex_lock(&out->lock);
1393 stop_compressed_output_l(out);
1394 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1395
1396 pthread_mutex_unlock(&out->lock);
1397 pthread_join(out->offload_thread, (void **) NULL);
1398 pthread_cond_destroy(&out->offload_cond);
1399
1400 return 0;
1401}
1402
Eric Laurent07eeafd2013-10-06 12:52:49 -07001403static bool allow_hdmi_channel_config(struct audio_device *adev)
1404{
1405 struct listnode *node;
1406 struct audio_usecase *usecase;
1407 bool ret = true;
1408
1409 list_for_each(node, &adev->usecase_list) {
1410 usecase = node_to_item(node, struct audio_usecase, list);
1411 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1412 /*
1413 * If voice call is already existing, do not proceed further to avoid
1414 * disabling/enabling both RX and TX devices, CSD calls, etc.
1415 * Once the voice call done, the HDMI channels can be configured to
1416 * max channels of remaining use cases.
1417 */
1418 if (usecase->id == USECASE_VOICE_CALL) {
1419 ALOGD("%s: voice call is active, no change in HDMI channels",
1420 __func__);
1421 ret = false;
1422 break;
1423 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1424 ALOGD("%s: multi channel playback is active, "
1425 "no change in HDMI channels", __func__);
1426 ret = false;
1427 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001428 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001429 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001430 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1431 ", no change in HDMI channels", __func__,
1432 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001433 ret = false;
1434 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001435 }
1436 }
1437 }
1438 return ret;
1439}
1440
1441static int check_and_set_hdmi_channels(struct audio_device *adev,
1442 unsigned int channels)
1443{
1444 struct listnode *node;
1445 struct audio_usecase *usecase;
1446
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001447 unsigned int supported_channels = platform_edid_get_max_channels(
1448 adev->platform);
1449 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001450 /* Check if change in HDMI channel config is allowed */
1451 if (!allow_hdmi_channel_config(adev))
1452 return 0;
1453
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001454 if (channels > supported_channels)
1455 channels = supported_channels;
1456
Eric Laurent07eeafd2013-10-06 12:52:49 -07001457 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001458 ALOGD("%s: Requested channels are same as current channels(%d)",
1459 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001460 return 0;
1461 }
1462
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001463 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001464 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001465 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001466 adev->cur_hdmi_channels = channels;
1467
1468 /*
1469 * Deroute all the playback streams routed to HDMI so that
1470 * the back end is deactivated. Note that backend will not
1471 * be deactivated if any one stream is connected to it.
1472 */
1473 list_for_each(node, &adev->usecase_list) {
1474 usecase = node_to_item(node, struct audio_usecase, list);
1475 if (usecase->type == PCM_PLAYBACK &&
1476 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001477 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001478 }
1479 }
1480
1481 /*
1482 * Enable all the streams disabled above. Now the HDMI backend
1483 * will be activated with new channel configuration
1484 */
1485 list_for_each(node, &adev->usecase_list) {
1486 usecase = node_to_item(node, struct audio_usecase, list);
1487 if (usecase->type == PCM_PLAYBACK &&
1488 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001489 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001490 }
1491 }
1492
1493 return 0;
1494}
1495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496static int stop_output_stream(struct stream_out *out)
1497{
1498 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 struct audio_usecase *uc_info;
1500 struct audio_device *adev = out->dev;
1501
Eric Laurent994a6932013-07-17 11:51:42 -07001502 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 uc_info = get_usecase_from_list(adev, out->usecase);
1505 if (uc_info == NULL) {
1506 ALOGE("%s: Could not find the usecase (%d) in the list",
1507 __func__, out->usecase);
1508 return -EINVAL;
1509 }
1510
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001511 if (is_offload_usecase(out->usecase) &&
1512 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001513 if (adev->visualizer_stop_output != NULL)
1514 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001515
1516 audio_extn_dts_remove_state_notifier_node(out->usecase);
1517
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001518 if (adev->offload_effects_stop_output != NULL)
1519 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1520 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001521
Eric Laurent150dbfe2013-02-27 14:31:02 -08001522 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001523 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524
1525 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001526 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001528 list_remove(&uc_info->list);
1529 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001531 if (is_offload_usecase(out->usecase) &&
1532 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1533 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1534 ALOGV("Disable passthrough , reset mixer to pcm");
1535 /* NO_PASSTHROUGH */
1536 out->compr_config.codec->compr_passthr = 0;
1537 audio_extn_dolby_set_hdmi_config(adev, out);
1538 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1539 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001540 /* Must be called after removing the usecase from list */
1541 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1542 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1543
Eric Laurent994a6932013-07-17 11:51:42 -07001544 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 return ret;
1546}
1547
1548int start_output_stream(struct stream_out *out)
1549{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001551 int sink_channels = 0;
1552 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 struct audio_usecase *uc_info;
1554 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301555 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001557 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1558 ret = -EINVAL;
1559 goto error_config;
1560 }
1561
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301562 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1563 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1564 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301565
Naresh Tanniru80659832014-06-04 18:17:56 +05301566 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301567 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301568 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301569 goto error_config;
1570 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301571
Eric Laurentb23d5282013-05-14 15:27:20 -07001572 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 if (out->pcm_device_id < 0) {
1574 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1575 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001576 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001577 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 }
1579
1580 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001581
1582 if (!uc_info) {
1583 ret = -ENOMEM;
1584 goto error_config;
1585 }
1586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 uc_info->id = out->usecase;
1588 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001589 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 uc_info->devices = out->devices;
1591 uc_info->in_snd_device = SND_DEVICE_NONE;
1592 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001593 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001594 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001595 if (is_offload_usecase(out->usecase)) {
1596 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001597 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1598 }
1599 }
Mingming Yin9c041392014-05-01 15:37:31 -07001600 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1601 if (!strncmp("true", prop_value, 4)) {
1602 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001603 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1604 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001605 check_and_set_hdmi_channels(adev, sink_channels);
1606 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001607 if (is_offload_usecase(out->usecase)) {
1608 unsigned int ch_count = out->compr_config.codec->ch_in;
1609 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1610 /* backend channel config for passthrough stream is stereo */
1611 ch_count = 2;
1612 check_and_set_hdmi_channels(adev, ch_count);
1613 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001614 check_and_set_hdmi_channels(adev, out->config.channels);
1615 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001616 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001617 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001618 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 select_devices(adev, out->usecase);
1621
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001622 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1623 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001624 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001625 unsigned int flags = PCM_OUT;
1626 unsigned int pcm_open_retry_count = 0;
1627 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1628 flags |= PCM_MMAP | PCM_NOIRQ;
1629 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1630 } else
1631 flags |= PCM_MONOTONIC;
1632
1633 while (1) {
1634 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1635 flags, &out->config);
1636 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1637 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1638 if (out->pcm != NULL) {
1639 pcm_close(out->pcm);
1640 out->pcm = NULL;
1641 }
1642 if (pcm_open_retry_count-- == 0) {
1643 ret = -EIO;
1644 goto error_open;
1645 }
1646 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1647 continue;
1648 }
1649 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001650 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001651
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001652 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1653 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001654
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001655 ALOGV("%s: pcm_prepare", __func__);
1656 if (pcm_is_ready(out->pcm)) {
1657 ret = pcm_prepare(out->pcm);
1658 if (ret < 0) {
1659 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1660 pcm_close(out->pcm);
1661 out->pcm = NULL;
1662 goto error_open;
1663 }
1664 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001665 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001666 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1667 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001669 out->compr = compress_open(adev->snd_card,
1670 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671 COMPRESS_IN, &out->compr_config);
1672 if (out->compr && !is_compress_ready(out->compr)) {
1673 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1674 compress_close(out->compr);
1675 out->compr = NULL;
1676 ret = -EIO;
1677 goto error_open;
1678 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301679 /* compress_open sends params of the track, so reset the flag here */
1680 out->is_compr_metadata_avail = false;
1681
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001682 if (out->offload_callback)
1683 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001684
Fred Oh3f43e742015-03-04 18:42:34 -08001685 /* Since small bufs uses blocking writes, a write will be blocked
1686 for the default max poll time (20s) in the event of an SSR.
1687 Reduce the poll time to observe and deal with SSR faster.
1688 */
1689 if (out->use_small_bufs) {
1690 compress_set_max_poll_wait(out->compr, 1000);
1691 }
1692
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001693 audio_extn_dts_create_state_notifier_node(out->usecase);
1694 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1695 popcount(out->channel_mask),
1696 out->playback_started);
1697
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001698#ifdef DS1_DOLBY_DDP_ENABLED
1699 if (audio_extn_is_dolby_format(out->format))
1700 audio_extn_dolby_send_ddp_endp_params(adev);
1701#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001702 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1703 if (adev->visualizer_start_output != NULL)
1704 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1705 if (adev->offload_effects_start_output != NULL)
1706 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001707 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001710
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001711 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001716error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301717 /*
1718 * sleep 50ms to allow sufficient time for kernel
1719 * drivers to recover incases like SSR.
1720 */
1721 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001722 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723}
1724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725static int check_input_parameters(uint32_t sample_rate,
1726 audio_format_t format,
1727 int channel_count)
1728{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001729 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001731 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001732 !voice_extn_compress_voip_is_format_supported(format) &&
1733 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001734
1735 switch (channel_count) {
1736 case 1:
1737 case 2:
1738 case 6:
1739 break;
1740 default:
1741 ret = -EINVAL;
1742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743
1744 switch (sample_rate) {
1745 case 8000:
1746 case 11025:
1747 case 12000:
1748 case 16000:
1749 case 22050:
1750 case 24000:
1751 case 32000:
1752 case 44100:
1753 case 48000:
1754 break;
1755 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001756 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757 }
1758
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001759 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760}
1761
1762static size_t get_input_buffer_size(uint32_t sample_rate,
1763 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001764 int channel_count,
1765 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766{
1767 size_t size = 0;
1768
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001769 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1770 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001772 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001773 if (is_low_latency)
1774 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001775 /* ToDo: should use frame_size computed based on the format and
1776 channel_count here. */
1777 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001779 /* make sure the size is multiple of 32 bytes
1780 * At 48 kHz mono 16-bit PCM:
1781 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1782 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1783 */
1784 size += 0x1f;
1785 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001786
1787 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788}
1789
1790static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1791{
1792 struct stream_out *out = (struct stream_out *)stream;
1793
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795}
1796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001797static int out_set_sample_rate(struct audio_stream *stream __unused,
1798 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 return -ENOSYS;
1801}
1802
1803static size_t out_get_buffer_size(const struct audio_stream *stream)
1804{
1805 struct stream_out *out = (struct stream_out *)stream;
1806
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001807 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001809 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1810 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001811
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001812 return out->config.period_size *
1813 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814}
1815
1816static uint32_t out_get_channels(const struct audio_stream *stream)
1817{
1818 struct stream_out *out = (struct stream_out *)stream;
1819
1820 return out->channel_mask;
1821}
1822
1823static audio_format_t out_get_format(const struct audio_stream *stream)
1824{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 struct stream_out *out = (struct stream_out *)stream;
1826
1827 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828}
1829
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001830static int out_set_format(struct audio_stream *stream __unused,
1831 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832{
1833 return -ENOSYS;
1834}
1835
1836static int out_standby(struct audio_stream *stream)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001840
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301841 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1842 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001843 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1844 /* Ignore standby in case of voip call because the voip output
1845 * stream is closed in adev_close_output_stream()
1846 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301847 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001848 return 0;
1849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001851 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001853 if (adev->adm_deregister_stream)
1854 adev->adm_deregister_stream(adev->adm_data, out->handle);
1855
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001856 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001858 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001859 if (out->pcm) {
1860 pcm_close(out->pcm);
1861 out->pcm = NULL;
1862 }
1863 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001864 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301866 out->send_next_track_params = false;
1867 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001868 out->gapless_mdata.encoder_delay = 0;
1869 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001870 if (out->compr != NULL) {
1871 compress_close(out->compr);
1872 out->compr = NULL;
1873 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001876 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 }
1878 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001879 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 return 0;
1881}
1882
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001883static int out_dump(const struct audio_stream *stream __unused,
1884 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885{
1886 return 0;
1887}
1888
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001889static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1890{
1891 int ret = 0;
1892 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001893
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001894 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001895 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001896 return -EINVAL;
1897 }
1898
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301899 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001900
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001901 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1902 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301903 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001904 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001905 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1906 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301907 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001908 }
1909
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001910 ALOGV("%s new encoder delay %u and padding %u", __func__,
1911 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1912
1913 return 0;
1914}
1915
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001916static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1917{
1918 return out == adev->primary_output || out == adev->voice_tx_output;
1919}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1922{
1923 struct stream_out *out = (struct stream_out *)stream;
1924 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001925 struct audio_usecase *usecase;
1926 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 struct str_parms *parms;
1928 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001929 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001930 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931
sangwoobc677242013-08-08 16:53:43 +09001932 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001933 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301935 if (!parms)
1936 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001937 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1938 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001941 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301944 * When HDMI cable is unplugged/usb hs is disconnected the
1945 * music playback is paused and the policy manager sends routing=0
1946 * But the audioflingercontinues to write data until standby time
1947 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948 * Avoid this by routing audio to speaker until standby.
1949 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301950 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1951 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001952 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001953 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1954 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001955 }
1956
1957 /*
1958 * select_devices() call below switches all the usecases on the same
1959 * backend to the new device. Refer to check_usecases_codec_backend() in
1960 * the select_devices(). But how do we undo this?
1961 *
1962 * For example, music playback is active on headset (deep-buffer usecase)
1963 * and if we go to ringtones and select a ringtone, low-latency usecase
1964 * will be started on headset+speaker. As we can't enable headset+speaker
1965 * and headset devices at the same time, select_devices() switches the music
1966 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1967 * So when the ringtone playback is completed, how do we undo the same?
1968 *
1969 * We are relying on the out_set_parameters() call on deep-buffer output,
1970 * once the ringtone playback is ended.
1971 * NOTE: We should not check if the current devices are same as new devices.
1972 * Because select_devices() must be called to switch back the music
1973 * playback to headset.
1974 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001975 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976 out->devices = val;
1977
1978 if (!out->standby)
1979 select_devices(adev, out->usecase);
1980
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001981 if (output_drives_call(adev, out)) {
1982 if(!voice_is_in_call(adev)) {
1983 if (adev->mode == AUDIO_MODE_IN_CALL) {
1984 adev->current_call_output = out;
1985 ret = voice_start_call(adev);
1986 }
1987 } else {
1988 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001989 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001990 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001991 }
1992 }
1993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001995 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001997
1998 if (out == adev->primary_output) {
1999 pthread_mutex_lock(&adev->lock);
2000 audio_extn_set_parameters(adev, parms);
2001 pthread_mutex_unlock(&adev->lock);
2002 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002003 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002004 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002005 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002006
2007 audio_extn_dts_create_state_notifier_node(out->usecase);
2008 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2009 popcount(out->channel_mask),
2010 out->playback_started);
2011
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002012 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002013 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302016error:
Eric Laurent994a6932013-07-17 11:51:42 -07002017 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018 return ret;
2019}
2020
2021static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2022{
2023 struct stream_out *out = (struct stream_out *)stream;
2024 struct str_parms *query = str_parms_create_str(keys);
2025 char *str;
2026 char value[256];
2027 struct str_parms *reply = str_parms_create();
2028 size_t i, j;
2029 int ret;
2030 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002031
2032 if (!query || !reply) {
2033 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2034 return NULL;
2035 }
2036
Eric Laurent994a6932013-07-17 11:51:42 -07002037 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2039 if (ret >= 0) {
2040 value[0] = '\0';
2041 i = 0;
2042 while (out->supported_channel_masks[i] != 0) {
2043 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2044 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2045 if (!first) {
2046 strcat(value, "|");
2047 }
2048 strcat(value, out_channels_name_to_enum_table[j].name);
2049 first = false;
2050 break;
2051 }
2052 }
2053 i++;
2054 }
2055 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2056 str = str_parms_to_str(reply);
2057 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002058 voice_extn_out_get_parameters(out, query, reply);
2059 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002060 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002061 free(str);
2062 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002063 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002065
2066 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2067 if (ret >= 0) {
2068 value[0] = '\0';
2069 i = 0;
2070 first = true;
2071 while (out->supported_formats[i] != 0) {
2072 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2073 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2074 if (!first) {
2075 strcat(value, "|");
2076 }
2077 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2078 first = false;
2079 break;
2080 }
2081 }
2082 i++;
2083 }
2084 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2085 str = str_parms_to_str(reply);
2086 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 str_parms_destroy(query);
2088 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002089 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 return str;
2091}
2092
2093static uint32_t out_get_latency(const struct audio_stream_out *stream)
2094{
2095 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002096 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097
Alexy Josephaa54c872014-12-03 02:46:47 -08002098 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002099 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002100 } else {
2101 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002103 }
2104
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302105 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002106 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107}
2108
2109static int out_set_volume(struct audio_stream_out *stream, float left,
2110 float right)
2111{
Eric Laurenta9024de2013-04-04 09:19:12 -07002112 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 int volume[2];
2114
Eric Laurenta9024de2013-04-04 09:19:12 -07002115 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2116 /* only take left channel into account: the API is for stereo anyway */
2117 out->muted = (left == 0.0f);
2118 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002119 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002120 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2121 /*
2122 * Set mute or umute on HDMI passthrough stream.
2123 * Only take left channel into account.
2124 * Mute is 0 and unmute 1
2125 */
2126 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2127 } else {
2128 char mixer_ctl_name[128];
2129 struct audio_device *adev = out->dev;
2130 struct mixer_ctl *ctl;
2131 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002132 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002134 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2135 "Compress Playback %d Volume", pcm_device_id);
2136 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2137 if (!ctl) {
2138 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2139 __func__, mixer_ctl_name);
2140 return -EINVAL;
2141 }
2142 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2143 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2144 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2145 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002147 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 return -ENOSYS;
2150}
2151
2152static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2153 size_t bytes)
2154{
2155 struct stream_out *out = (struct stream_out *)stream;
2156 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302157 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002158 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302161
Naresh Tanniru80659832014-06-04 18:17:56 +05302162 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002163 // increase written size during SSR to avoid mismatch
2164 // with the written frames count in AF
2165 if (!is_offload_usecase(out->usecase))
2166 out->written += bytes / (out->config.channels * sizeof(short));
2167
Naresh Tanniru80659832014-06-04 18:17:56 +05302168 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302169 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302170 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302171 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002172 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302173 //during SSR for compress usecase we should return error to flinger
2174 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2175 pthread_mutex_unlock(&out->lock);
2176 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302177 }
2178 }
2179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002181 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002182 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002183 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2184 ret = voice_extn_compress_voip_start_output_stream(out);
2185 else
2186 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002187 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002188 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002190 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 goto exit;
2192 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002193 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2194 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002197 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002198 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002199 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002200 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002201 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2202 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302203 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2204 ALOGD("copl(%p):send next track params in gapless", out);
2205 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2206 out->send_next_track_params = false;
2207 out->is_compr_metadata_avail = false;
2208 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002209 }
2210
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002211 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302212 if (ret < 0)
2213 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002214 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002215 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302216 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002217 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302218 } else if (-ENETRESET == ret) {
2219 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2220 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2221 pthread_mutex_unlock(&out->lock);
2222 out_standby(&out->stream.common);
2223 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302225 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002227 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 out->playback_started = 1;
2229 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002230
2231 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2232 popcount(out->channel_mask),
2233 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 }
2235 pthread_mutex_unlock(&out->lock);
2236 return ret;
2237 } else {
2238 if (out->pcm) {
2239 if (out->muted)
2240 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002241
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002243
2244 if (adev->adm_request_focus)
2245 adev->adm_request_focus(adev->adm_data, out->handle);
2246
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002247 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2248 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2249 else
2250 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002251
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302252 if (ret < 0)
2253 ret = -errno;
2254 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002255 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002256
2257 if (adev->adm_abandon_focus)
2258 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 }
2261
2262exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302263 /* ToDo: There may be a corner case when SSR happens back to back during
2264 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302265 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302266 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302267 }
2268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269 pthread_mutex_unlock(&out->lock);
2270
2271 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002272 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002273 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302274 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302275 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302276 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302277 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302278 out->standby = true;
2279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002281 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302282 out_get_sample_rate(&out->stream.common));
2283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 }
2285 return bytes;
2286}
2287
2288static int out_get_render_position(const struct audio_stream_out *stream,
2289 uint32_t *dsp_frames)
2290{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302292 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002293
2294 if (dsp_frames == NULL)
2295 return -EINVAL;
2296
2297 *dsp_frames = 0;
2298 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002299 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 pthread_mutex_lock(&out->lock);
2301 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302302 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002303 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302304 if (ret < 0)
2305 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306 ALOGVV("%s rendered frames %d sample_rate %d",
2307 __func__, *dsp_frames, out->sample_rate);
2308 }
2309 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302310 if (-ENETRESET == ret) {
2311 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2312 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2313 return -EINVAL;
2314 } else if(ret < 0) {
2315 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2316 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302317 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2318 /*
2319 * Handle corner case where compress session is closed during SSR
2320 * and timestamp is queried
2321 */
2322 ALOGE(" ERROR: sound card not active, return error");
2323 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302324 } else {
2325 return 0;
2326 }
Zhou Song32a556e2015-05-05 10:46:56 +08002327 } else if (audio_is_linear_pcm(out->format)) {
2328 *dsp_frames = out->written;
2329 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330 } else
2331 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332}
2333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002334static int out_add_audio_effect(const struct audio_stream *stream __unused,
2335 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336{
2337 return 0;
2338}
2339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002340static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2341 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342{
2343 return 0;
2344}
2345
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002346static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2347 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348{
2349 return -EINVAL;
2350}
2351
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002352static int out_get_presentation_position(const struct audio_stream_out *stream,
2353 uint64_t *frames, struct timespec *timestamp)
2354{
2355 struct stream_out *out = (struct stream_out *)stream;
2356 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002357 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002358
2359 pthread_mutex_lock(&out->lock);
2360
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002361 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002362 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302363 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002364 &out->sample_rate);
2365 ALOGVV("%s rendered frames %ld sample_rate %d",
2366 __func__, dsp_frames, out->sample_rate);
2367 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302368 if (ret < 0)
2369 ret = -errno;
2370 if (-ENETRESET == ret) {
2371 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2372 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2373 ret = -EINVAL;
2374 } else
2375 ret = 0;
2376
Eric Laurent949a0892013-09-20 09:20:13 -07002377 /* this is the best we can do */
2378 clock_gettime(CLOCK_MONOTONIC, timestamp);
2379 }
2380 } else {
2381 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002382 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002383 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2384 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002385 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002386 // This adjustment accounts for buffering after app processor.
2387 // It is based on estimated DSP latency per use case, rather than exact.
2388 signed_frames -=
2389 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2390
Eric Laurent949a0892013-09-20 09:20:13 -07002391 // It would be unusual for this value to be negative, but check just in case ...
2392 if (signed_frames >= 0) {
2393 *frames = signed_frames;
2394 ret = 0;
2395 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002396 }
2397 }
2398 }
2399
2400 pthread_mutex_unlock(&out->lock);
2401
2402 return ret;
2403}
2404
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405static int out_set_callback(struct audio_stream_out *stream,
2406 stream_callback_t callback, void *cookie)
2407{
2408 struct stream_out *out = (struct stream_out *)stream;
2409
2410 ALOGV("%s", __func__);
2411 pthread_mutex_lock(&out->lock);
2412 out->offload_callback = callback;
2413 out->offload_cookie = cookie;
2414 pthread_mutex_unlock(&out->lock);
2415 return 0;
2416}
2417
2418static int out_pause(struct audio_stream_out* stream)
2419{
2420 struct stream_out *out = (struct stream_out *)stream;
2421 int status = -ENOSYS;
2422 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002423 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002424 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002425 pthread_mutex_lock(&out->lock);
2426 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302427 struct audio_device *adev = out->dev;
2428 int snd_scard_state = get_snd_card_state(adev);
2429
2430 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2431 status = compress_pause(out->compr);
2432
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002433 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002434
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302435 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002436 audio_extn_dts_notify_playback_state(out->usecase, 0,
2437 out->sample_rate, popcount(out->channel_mask),
2438 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 }
2440 pthread_mutex_unlock(&out->lock);
2441 }
2442 return status;
2443}
2444
2445static int out_resume(struct audio_stream_out* stream)
2446{
2447 struct stream_out *out = (struct stream_out *)stream;
2448 int status = -ENOSYS;
2449 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002450 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002451 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 status = 0;
2453 pthread_mutex_lock(&out->lock);
2454 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302455 struct audio_device *adev = out->dev;
2456 int snd_scard_state = get_snd_card_state(adev);
2457
2458 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2459 status = compress_resume(out->compr);
2460
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002462
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302463 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002464 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2465 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 }
2467 pthread_mutex_unlock(&out->lock);
2468 }
2469 return status;
2470}
2471
2472static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2473{
2474 struct stream_out *out = (struct stream_out *)stream;
2475 int status = -ENOSYS;
2476 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002477 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478 pthread_mutex_lock(&out->lock);
2479 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2480 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2481 else
2482 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2483 pthread_mutex_unlock(&out->lock);
2484 }
2485 return status;
2486}
2487
2488static int out_flush(struct audio_stream_out* stream)
2489{
2490 struct stream_out *out = (struct stream_out *)stream;
2491 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002492 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002493 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 pthread_mutex_lock(&out->lock);
2495 stop_compressed_output_l(out);
2496 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002497 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002498 return 0;
2499 }
2500 return -ENOSYS;
2501}
2502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503/** audio_stream_in implementation **/
2504static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2505{
2506 struct stream_in *in = (struct stream_in *)stream;
2507
2508 return in->config.rate;
2509}
2510
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002511static int in_set_sample_rate(struct audio_stream *stream __unused,
2512 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513{
2514 return -ENOSYS;
2515}
2516
2517static size_t in_get_buffer_size(const struct audio_stream *stream)
2518{
2519 struct stream_in *in = (struct stream_in *)stream;
2520
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002521 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2522 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002523 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2524 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002525
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002526 return in->config.period_size *
2527 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528}
2529
2530static uint32_t in_get_channels(const struct audio_stream *stream)
2531{
2532 struct stream_in *in = (struct stream_in *)stream;
2533
2534 return in->channel_mask;
2535}
2536
2537static audio_format_t in_get_format(const struct audio_stream *stream)
2538{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002539 struct stream_in *in = (struct stream_in *)stream;
2540
2541 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542}
2543
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002544static int in_set_format(struct audio_stream *stream __unused,
2545 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546{
2547 return -ENOSYS;
2548}
2549
2550static int in_standby(struct audio_stream *stream)
2551{
2552 struct stream_in *in = (struct stream_in *)stream;
2553 struct audio_device *adev = in->dev;
2554 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302555 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2556 stream, in->usecase, use_case_table[in->usecase]);
2557
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002558 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2559 /* Ignore standby in case of voip call because the voip input
2560 * stream is closed in adev_close_input_stream()
2561 */
2562 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2563 return status;
2564 }
2565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002567 if (!in->standby && in->is_st_session) {
2568 ALOGD("%s: sound trigger pcm stop lab", __func__);
2569 audio_extn_sound_trigger_stop_lab(in);
2570 in->standby = 1;
2571 }
2572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002574 if (adev->adm_deregister_stream)
2575 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2576
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002577 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002579 if (in->pcm) {
2580 pcm_close(in->pcm);
2581 in->pcm = NULL;
2582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002584 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 }
2586 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002587 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 return status;
2589}
2590
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002591static int in_dump(const struct audio_stream *stream __unused,
2592 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593{
2594 return 0;
2595}
2596
2597static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2598{
2599 struct stream_in *in = (struct stream_in *)stream;
2600 struct audio_device *adev = in->dev;
2601 struct str_parms *parms;
2602 char *str;
2603 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002604 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302606 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 parms = str_parms_create_str(kvpairs);
2608
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302609 if (!parms)
2610 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002612 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002613
2614 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2615 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 val = atoi(value);
2617 /* no audio source uses val == 0 */
2618 if ((in->source != val) && (val != 0)) {
2619 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002620 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2621 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2622 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2623 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002624 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002625 err = voice_extn_compress_voip_open_input_stream(in);
2626 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002627 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002628 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002629 }
2630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 }
2632 }
2633
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002634 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2635 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002637 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 in->device = val;
2639 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002640 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002641 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 }
2643 }
2644
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002645done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002647 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648
2649 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302650error:
Eric Laurent994a6932013-07-17 11:51:42 -07002651 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 return ret;
2653}
2654
2655static char* in_get_parameters(const struct audio_stream *stream,
2656 const char *keys)
2657{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002658 struct stream_in *in = (struct stream_in *)stream;
2659 struct str_parms *query = str_parms_create_str(keys);
2660 char *str;
2661 char value[256];
2662 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002663
2664 if (!query || !reply) {
2665 ALOGE("in_get_parameters: failed to create query or reply");
2666 return NULL;
2667 }
2668
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002669 ALOGV("%s: enter: keys - %s", __func__, keys);
2670
2671 voice_extn_in_get_parameters(in, query, reply);
2672
2673 str = str_parms_to_str(reply);
2674 str_parms_destroy(query);
2675 str_parms_destroy(reply);
2676
2677 ALOGV("%s: exit: returns - %s", __func__, str);
2678 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679}
2680
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002681static int in_set_gain(struct audio_stream_in *stream __unused,
2682 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683{
2684 return 0;
2685}
2686
2687static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2688 size_t bytes)
2689{
2690 struct stream_in *in = (struct stream_in *)stream;
2691 struct audio_device *adev = in->dev;
2692 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302693 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302696
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002697 if (in->is_st_session) {
2698 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2699 /* Read from sound trigger HAL */
2700 audio_extn_sound_trigger_read(in, buffer, bytes);
2701 pthread_mutex_unlock(&in->lock);
2702 return bytes;
2703 }
2704
2705 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2706 ALOGD(" %s: sound card is not active/SSR state", __func__);
2707 ret= -EIO;;
2708 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302709 }
2710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002712 pthread_mutex_lock(&adev->lock);
2713 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2714 ret = voice_extn_compress_voip_start_input_stream(in);
2715 else
2716 ret = start_input_stream(in);
2717 pthread_mutex_unlock(&adev->lock);
2718 if (ret != 0) {
2719 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 }
2721 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002722 if (adev->adm_register_input_stream)
2723 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002726 if (adev->adm_request_focus)
2727 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002730 if (audio_extn_ssr_get_enabled() &&
2731 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002732 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002733 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2734 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002735 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2736 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002737 else
2738 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302739 if (ret < 0)
2740 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 }
2742
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002743 if (adev->adm_abandon_focus)
2744 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 /*
2747 * Instead of writing zeroes here, we could trust the hardware
2748 * to always provide zeroes when muted.
2749 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302750 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2751 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 memset(buffer, 0, bytes);
2753
2754exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302755 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302756 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002757 if (-ENETRESET == ret)
2758 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 pthread_mutex_unlock(&in->lock);
2761
2762 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302763 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302764 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302765 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302766 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302767 in->standby = true;
2768 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302769 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002771 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002772 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302773 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 }
2775 return bytes;
2776}
2777
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002778static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779{
2780 return 0;
2781}
2782
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002783static int add_remove_audio_effect(const struct audio_stream *stream,
2784 effect_handle_t effect,
2785 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002787 struct stream_in *in = (struct stream_in *)stream;
2788 int status = 0;
2789 effect_descriptor_t desc;
2790
2791 status = (*effect)->get_descriptor(effect, &desc);
2792 if (status != 0)
2793 return status;
2794
2795 pthread_mutex_lock(&in->lock);
2796 pthread_mutex_lock(&in->dev->lock);
2797 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2798 in->enable_aec != enable &&
2799 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2800 in->enable_aec = enable;
2801 if (!in->standby)
2802 select_devices(in->dev, in->usecase);
2803 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002804 if (in->enable_ns != enable &&
2805 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2806 in->enable_ns = enable;
2807 if (!in->standby)
2808 select_devices(in->dev, in->usecase);
2809 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002810 pthread_mutex_unlock(&in->dev->lock);
2811 pthread_mutex_unlock(&in->lock);
2812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 return 0;
2814}
2815
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002816static int in_add_audio_effect(const struct audio_stream *stream,
2817 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818{
Eric Laurent994a6932013-07-17 11:51:42 -07002819 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002820 return add_remove_audio_effect(stream, effect, true);
2821}
2822
2823static int in_remove_audio_effect(const struct audio_stream *stream,
2824 effect_handle_t effect)
2825{
Eric Laurent994a6932013-07-17 11:51:42 -07002826 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002827 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828}
2829
2830static int adev_open_output_stream(struct audio_hw_device *dev,
2831 audio_io_handle_t handle,
2832 audio_devices_t devices,
2833 audio_output_flags_t flags,
2834 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002835 struct audio_stream_out **stream_out,
2836 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837{
2838 struct audio_device *adev = (struct audio_device *)dev;
2839 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002840 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002841 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302844
2845 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2846 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002847 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302848 return -EINVAL;
2849 }
2850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2852
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302853 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2854 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2855 devices, flags, &out->stream);
2856
2857
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002858 if (!out) {
2859 return -ENOMEM;
2860 }
2861
Haynes Mathew George204045b2015-02-25 20:32:03 -08002862 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2863 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 if (devices == AUDIO_DEVICE_NONE)
2866 devices = AUDIO_DEVICE_OUT_SPEAKER;
2867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 out->flags = flags;
2869 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002870 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002871 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 out->sample_rate = config->sample_rate;
2873 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2874 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002875 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002876 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002877 out->non_blocking = 0;
2878 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879
2880 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002881 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2882 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002883 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2884 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2885
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002886 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002887 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2888 ret = read_hdmi_channel_masks(out);
2889
2890 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2891 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002892 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002893 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002894 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002895
2896 if (config->sample_rate == 0)
2897 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2898 if (config->channel_mask == 0)
2899 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2900
2901 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2904 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002906 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002908 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2909 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002910 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002911 ret = voice_extn_compress_voip_open_output_stream(out);
2912 if (ret != 0) {
2913 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2914 __func__, ret);
2915 goto error_open;
2916 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002917 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2918 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2921 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2922 ALOGE("%s: Unsupported Offload information", __func__);
2923 ret = -EINVAL;
2924 goto error_open;
2925 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002926
2927 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2928 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2929 ALOGV("read and update_pass through formats");
2930 ret = audio_extn_dolby_update_passt_formats(adev, out);
2931 if(ret != 0) {
2932 goto error_open;
2933 }
2934 if(config->offload_info.format == 0)
2935 config->offload_info.format = out->supported_formats[0];
2936 }
2937
Mingming Yin90310102013-11-13 16:57:00 -08002938 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002939 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002940 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002941 ret = -EINVAL;
2942 goto error_open;
2943 }
2944
2945 out->compr_config.codec = (struct snd_codec *)
2946 calloc(1, sizeof(struct snd_codec));
2947
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002948 if (!out->compr_config.codec) {
2949 ret = -ENOMEM;
2950 goto error_open;
2951 }
2952
vivek mehta0ea887a2015-08-26 14:01:20 -07002953 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2954 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2955 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2956 } else {
2957 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2958 out->usecase = get_offload_usecase(adev);
Mingming Yin21d60472015-09-30 13:56:25 -07002959
2960 out->stream.set_callback = out_set_callback;
2961 out->stream.pause = out_pause;
2962 out->stream.resume = out_resume;
2963 out->stream.drain = out_drain;
2964 out->stream.flush = out_flush;
vivek mehta0ea887a2015-08-26 14:01:20 -07002965 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002966 if (config->offload_info.channel_mask)
2967 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002968 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002970 config->offload_info.channel_mask = config->channel_mask;
2971 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002972 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 out->sample_rate = config->offload_info.sample_rate;
2974
Mingming Yin3ee55c62014-08-04 14:23:35 -07002975 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002976
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002977 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002978 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002979 audio_extn_dolby_get_snd_codec_id(adev, out,
2980 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002981 else
2982 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002984
2985 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2986 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002987 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002988 platform_get_pcm_offload_buffer_size(&config->offload_info);
2989 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2990 out->compr_config.fragment_size =
2991 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002992 } else {
2993 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002994 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002995 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2997 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002998 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002999 out->compr_config.codec->bit_rate =
3000 config->offload_info.bit_rate;
3001 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003002 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303004 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003005 /*TODO: Do we need to change it for passthrough */
3006 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007
Manish Dewangana6fc5442015-08-24 20:30:31 +05303008 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3009 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3010 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3011 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003012 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3013 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003014 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003015 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003016 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3017 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003018
Mingming Yin3ee55c62014-08-04 14:23:35 -07003019 if (out->bit_width == 24) {
3020 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3021 }
3022
Amit Shekhar6f461b12014-08-01 14:52:58 -07003023 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303024 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3027 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003028
Mingming Yin497419f2015-07-01 16:57:32 -07003029 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003030 //this flag is set from framework only if its for PCM formats
3031 //no need to check for PCM format again
3032 out->non_blocking = 0;
3033 out->use_small_bufs = true;
3034 ALOGI("Keep write blocking for small buff: non_blockling %d",
3035 out->non_blocking);
3036 }
3037
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003038 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303039 out->send_next_track_params = false;
3040 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003041 out->offload_state = OFFLOAD_STATE_IDLE;
3042 out->playback_started = 0;
3043
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003044 audio_extn_dts_create_state_notifier_node(out->usecase);
3045
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 create_offload_callback_thread(out);
3047 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3048 __func__, config->offload_info.version,
3049 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003050 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003051 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003052 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3053 ret = voice_check_and_set_incall_music_usecase(adev, out);
3054 if (ret != 0) {
3055 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3056 __func__, ret);
3057 goto error_open;
3058 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003059 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3060 if (config->sample_rate == 0)
3061 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3062 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3063 config->sample_rate != 8000) {
3064 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3065 ret = -EINVAL;
3066 goto error_open;
3067 }
3068 out->sample_rate = config->sample_rate;
3069 out->config.rate = config->sample_rate;
3070 if (config->format == AUDIO_FORMAT_DEFAULT)
3071 config->format = AUDIO_FORMAT_PCM_16_BIT;
3072 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3073 config->format = AUDIO_FORMAT_PCM_16_BIT;
3074 ret = -EINVAL;
3075 goto error_open;
3076 }
3077 out->format = config->format;
3078 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3079 out->config = pcm_config_afe_proxy_playback;
3080 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003081 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3082 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3083 out->config = pcm_config_low_latency;
3084 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003085 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003086 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3088 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003090 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3091 format = AUDIO_FORMAT_PCM_16_BIT;
3092 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3093 out->config = pcm_config_deep_buffer;
3094 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003095 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003096 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003097 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003098 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003099 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003100 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 }
3102
Amit Shekhar1d896042014-10-03 13:16:09 -07003103 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3104 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003105 /* TODO remove this hardcoding and check why width is zero*/
3106 if (out->bit_width == 0)
3107 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003108 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3109 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003110 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003111 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003112 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3113 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3114 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003115 if(adev->primary_output == NULL)
3116 adev->primary_output = out;
3117 else {
3118 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003119 ret = -EEXIST;
3120 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003121 }
3122 }
3123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 /* Check if this usecase is already existing */
3125 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003126 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3127 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003130 ret = -EEXIST;
3131 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 }
3133 pthread_mutex_unlock(&adev->lock);
3134
3135 out->stream.common.get_sample_rate = out_get_sample_rate;
3136 out->stream.common.set_sample_rate = out_set_sample_rate;
3137 out->stream.common.get_buffer_size = out_get_buffer_size;
3138 out->stream.common.get_channels = out_get_channels;
3139 out->stream.common.get_format = out_get_format;
3140 out->stream.common.set_format = out_set_format;
3141 out->stream.common.standby = out_standby;
3142 out->stream.common.dump = out_dump;
3143 out->stream.common.set_parameters = out_set_parameters;
3144 out->stream.common.get_parameters = out_get_parameters;
3145 out->stream.common.add_audio_effect = out_add_audio_effect;
3146 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3147 out->stream.get_latency = out_get_latency;
3148 out->stream.set_volume = out_set_volume;
3149 out->stream.write = out_write;
3150 out->stream.get_render_position = out_get_render_position;
3151 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003152 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003155 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003156 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
3158 config->format = out->stream.common.get_format(&out->stream.common);
3159 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3160 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3161
3162 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303163 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003164 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003165
3166 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3167 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3168 popcount(out->channel_mask), out->playback_started);
3169
Eric Laurent994a6932013-07-17 11:51:42 -07003170 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003172
3173error_open:
3174 free(out);
3175 *stream_out = NULL;
3176 ALOGD("%s: exit: ret %d", __func__, ret);
3177 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178}
3179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003180static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 struct audio_stream_out *stream)
3182{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003183 struct stream_out *out = (struct stream_out *)stream;
3184 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003185 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003186
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303187 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3188
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003189 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303190 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003191 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303192 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003193 if(ret != 0)
3194 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3195 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003196 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003197 out_standby(&stream->common);
3198
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003199 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003200 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003202 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003203 if (out->compr_config.codec != NULL)
3204 free(out->compr_config.codec);
3205 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003206
3207 if (adev->voice_tx_output == out)
3208 adev->voice_tx_output = NULL;
3209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003210 pthread_cond_destroy(&out->cond);
3211 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003213 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214}
3215
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003216static void close_compress_sessions(struct audio_device *adev)
3217{
Mingming Yin7b762e72015-03-04 13:47:32 -08003218 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303219 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003220 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003221 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303222
3223 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003224 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303225 if (is_offload_usecase(usecase->id)) {
3226 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003227 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3228 out = usecase->stream.out;
3229 pthread_mutex_unlock(&adev->lock);
3230 out_standby(&out->stream.common);
3231 pthread_mutex_lock(&adev->lock);
3232 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303233 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003234 }
3235 pthread_mutex_unlock(&adev->lock);
3236}
3237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3239{
3240 struct audio_device *adev = (struct audio_device *)dev;
3241 struct str_parms *parms;
3242 char *str;
3243 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003244 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003245 int ret;
3246 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003248 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303251 if (!parms)
3252 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003253 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3254 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303255 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303256 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303257 struct listnode *node;
3258 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303259 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303260 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003261 //close compress sessions on OFFLINE status
3262 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303263 } else if (strstr(snd_card_status, "ONLINE")) {
3264 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303265 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003266 //send dts hpx license if enabled
3267 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303268 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303269 }
3270
3271 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003272 status = voice_set_parameters(adev, parms);
3273 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003274 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003276 status = platform_set_parameters(adev->platform, parms);
3277 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003278 goto done;
3279
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003280 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3281 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003282 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3284 adev->bluetooth_nrec = true;
3285 else
3286 adev->bluetooth_nrec = false;
3287 }
3288
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003289 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3290 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3292 adev->screen_off = false;
3293 else
3294 adev->screen_off = true;
3295 }
3296
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003297 ret = str_parms_get_int(parms, "rotation", &val);
3298 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003299 bool reverse_speakers = false;
3300 switch(val) {
3301 // FIXME: note that the code below assumes that the speakers are in the correct placement
3302 // relative to the user when the device is rotated 90deg from its default rotation. This
3303 // assumption is device-specific, not platform-specific like this code.
3304 case 270:
3305 reverse_speakers = true;
3306 break;
3307 case 0:
3308 case 90:
3309 case 180:
3310 break;
3311 default:
3312 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003313 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003314 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003315 if (status == 0) {
3316 if (adev->speaker_lr_swap != reverse_speakers) {
3317 adev->speaker_lr_swap = reverse_speakers;
3318 // only update the selected device if there is active pcm playback
3319 struct audio_usecase *usecase;
3320 struct listnode *node;
3321 list_for_each(node, &adev->usecase_list) {
3322 usecase = node_to_item(node, struct audio_usecase, list);
3323 if (usecase->type == PCM_PLAYBACK) {
3324 select_devices(adev, usecase->id);
3325 break;
3326 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003327 }
3328 }
3329 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003330 }
3331
Mingming Yin514a8bc2014-07-29 15:22:21 -07003332 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3333 if (ret >= 0) {
3334 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3335 adev->bt_wb_speech_enabled = true;
3336 else
3337 adev->bt_wb_speech_enabled = false;
3338 }
3339
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003340 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3341 if (ret >= 0) {
3342 val = atoi(value);
3343 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3344 ALOGV("cache new edid");
3345 platform_cache_edid(adev->platform);
3346 }
3347 }
3348
3349 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3350 if (ret >= 0) {
3351 val = atoi(value);
3352 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3353 ALOGV("invalidate cached edid");
3354 platform_invalidate_edid(adev->platform);
3355 }
3356 }
3357
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003358 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003359
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003360done:
3361 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003362 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303363error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003364 ALOGV("%s: exit with code(%d)", __func__, status);
3365 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366}
3367
3368static char* adev_get_parameters(const struct audio_hw_device *dev,
3369 const char *keys)
3370{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003371 struct audio_device *adev = (struct audio_device *)dev;
3372 struct str_parms *reply = str_parms_create();
3373 struct str_parms *query = str_parms_create_str(keys);
3374 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303375 char value[256] = {0};
3376 int ret = 0;
3377
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003378 if (!query || !reply) {
3379 ALOGE("adev_get_parameters: failed to create query or reply");
3380 return NULL;
3381 }
3382
Naresh Tannirud7205b62014-06-20 02:54:48 +05303383 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3384 sizeof(value));
3385 if (ret >=0) {
3386 int val = 1;
3387 pthread_mutex_lock(&adev->snd_card_status.lock);
3388 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3389 val = 0;
3390 pthread_mutex_unlock(&adev->snd_card_status.lock);
3391 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3392 goto exit;
3393 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003394
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003395 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003396 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003397 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003398 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303399 pthread_mutex_unlock(&adev->lock);
3400
Naresh Tannirud7205b62014-06-20 02:54:48 +05303401exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003402 str = str_parms_to_str(reply);
3403 str_parms_destroy(query);
3404 str_parms_destroy(reply);
3405
3406 ALOGV("%s: exit: returns - %s", __func__, str);
3407 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408}
3409
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003410static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411{
3412 return 0;
3413}
3414
3415static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3416{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003417 int ret;
3418 struct audio_device *adev = (struct audio_device *)dev;
3419 pthread_mutex_lock(&adev->lock);
3420 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003421 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003422 pthread_mutex_unlock(&adev->lock);
3423 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424}
3425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003426static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3427 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428{
3429 return -ENOSYS;
3430}
3431
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003432static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3433 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434{
3435 return -ENOSYS;
3436}
3437
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003438static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3439 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440{
3441 return -ENOSYS;
3442}
3443
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003444static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3445 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446{
3447 return -ENOSYS;
3448}
3449
3450static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3451{
3452 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 pthread_mutex_lock(&adev->lock);
3455 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003456 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003458 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3459 voice_is_in_call(adev)) {
3460 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003461 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003462 adev->current_call_output = NULL;
3463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 }
3465 pthread_mutex_unlock(&adev->lock);
3466 return 0;
3467}
3468
3469static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3470{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003471 int ret;
3472
3473 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003474 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003475 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3476 pthread_mutex_unlock(&adev->lock);
3477
3478 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479}
3480
3481static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3482{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003483 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 return 0;
3485}
3486
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003487static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 const struct audio_config *config)
3489{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003490 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003492 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3493 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494}
3495
3496static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003497 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 audio_devices_t devices,
3499 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003500 struct audio_stream_in **stream_in,
3501 audio_input_flags_t flags __unused,
3502 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003503 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
3505 struct audio_device *adev = (struct audio_device *)dev;
3506 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003507 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003508 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003509 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 *stream_in = NULL;
3512 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3513 return -EINVAL;
3514
3515 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003516
3517 if (!in) {
3518 ALOGE("failed to allocate input stream");
3519 return -ENOMEM;
3520 }
3521
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303522 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003523 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3524 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003526 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 in->stream.common.get_sample_rate = in_get_sample_rate;
3529 in->stream.common.set_sample_rate = in_set_sample_rate;
3530 in->stream.common.get_buffer_size = in_get_buffer_size;
3531 in->stream.common.get_channels = in_get_channels;
3532 in->stream.common.get_format = in_get_format;
3533 in->stream.common.set_format = in_set_format;
3534 in->stream.common.standby = in_standby;
3535 in->stream.common.dump = in_dump;
3536 in->stream.common.set_parameters = in_set_parameters;
3537 in->stream.common.get_parameters = in_get_parameters;
3538 in->stream.common.add_audio_effect = in_add_audio_effect;
3539 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3540 in->stream.set_gain = in_set_gain;
3541 in->stream.read = in_read;
3542 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3543
3544 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003545 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 in->standby = 1;
3548 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003549 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003550 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551
3552 /* Update config params with the requested sample rate and channels */
3553 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003554 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3555 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3556 is_low_latency = true;
3557#if LOW_LATENCY_CAPTURE_USE_CASE
3558 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3559#endif
3560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003563 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003565 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303566 if (adev->mode != AUDIO_MODE_IN_CALL) {
3567 ret = -EINVAL;
3568 goto err_open;
3569 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003570 if (config->sample_rate == 0)
3571 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3572 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3573 config->sample_rate != 8000) {
3574 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3575 ret = -EINVAL;
3576 goto err_open;
3577 }
3578 if (config->format == AUDIO_FORMAT_DEFAULT)
3579 config->format = AUDIO_FORMAT_PCM_16_BIT;
3580 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3581 config->format = AUDIO_FORMAT_PCM_16_BIT;
3582 ret = -EINVAL;
3583 goto err_open;
3584 }
3585
3586 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3587 in->config = pcm_config_afe_proxy_record;
3588 in->config.channels = channel_count;
3589 in->config.rate = config->sample_rate;
3590 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003591 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003592 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003593 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3594 ret = -EINVAL;
3595 goto err_open;
3596 }
3597 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003598 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003599 }
Mingming Yine62d7842013-10-25 16:26:03 -07003600 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003601 audio_extn_compr_cap_format_supported(config->format) &&
3602 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003603 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003604 } else {
3605 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003606 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003607 buffer_size = get_input_buffer_size(config->sample_rate,
3608 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003609 channel_count,
3610 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003611 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003612 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3613 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3614 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3615 (in->config.rate == 8000 || in->config.rate == 16000) &&
3616 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3617 voice_extn_compress_voip_open_input_stream(in);
3618 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003619 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003621 /* This stream could be for sound trigger lab,
3622 get sound trigger pcm if present */
3623 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303624 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003627 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003628 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
3630err_open:
3631 free(in);
3632 *stream_in = NULL;
3633 return ret;
3634}
3635
3636static void adev_close_input_stream(struct audio_hw_device *dev,
3637 struct audio_stream_in *stream)
3638{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003639 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003640 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003641 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303642
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303643 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003644
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303645 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003646 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303647
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003648 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303649 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003650 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303651 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003652 if (ret != 0)
3653 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3654 __func__, ret);
3655 } else
3656 in_standby(&stream->common);
3657
Mingming Yin7b762e72015-03-04 13:47:32 -08003658 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003659 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003660 audio_extn_ssr_deinit();
3661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662
Mingming Yine62d7842013-10-25 16:26:03 -07003663 if(audio_extn_compr_cap_enabled() &&
3664 audio_extn_compr_cap_format_supported(in->config.format))
3665 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003666
3667 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 return;
3669}
3670
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003671static int adev_dump(const audio_hw_device_t *device __unused,
3672 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673{
3674 return 0;
3675}
3676
3677static int adev_close(hw_device_t *device)
3678{
3679 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003680
3681 if (!adev)
3682 return 0;
3683
3684 pthread_mutex_lock(&adev_init_lock);
3685
3686 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003687 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003688 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003689 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003690 audio_route_free(adev->audio_route);
3691 free(adev->snd_dev_ref_cnt);
3692 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003693 if (adev->adm_deinit)
3694 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003695 free(device);
3696 adev = NULL;
3697 }
3698 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 return 0;
3701}
3702
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003703/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3704 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3705 * just that it _might_ work.
3706 */
3707static int period_size_is_plausible_for_low_latency(int period_size)
3708{
3709 switch (period_size) {
3710 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003711 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003712 case 240:
3713 case 320:
3714 case 480:
3715 return 1;
3716 default:
3717 return 0;
3718 }
3719}
3720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721static int adev_open(const hw_module_t *module, const char *name,
3722 hw_device_t **device)
3723{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003724 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003726 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3728
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003729 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003730 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003731 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003732 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003733 ALOGD("%s: returning existing instance of adev", __func__);
3734 ALOGD("%s: exit", __func__);
3735 pthread_mutex_unlock(&adev_init_lock);
3736 return 0;
3737 }
3738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 adev = calloc(1, sizeof(struct audio_device));
3740
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003741 if (!adev) {
3742 pthread_mutex_unlock(&adev_init_lock);
3743 return -ENOMEM;
3744 }
3745
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003746 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3749 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3750 adev->device.common.module = (struct hw_module_t *)module;
3751 adev->device.common.close = adev_close;
3752
3753 adev->device.init_check = adev_init_check;
3754 adev->device.set_voice_volume = adev_set_voice_volume;
3755 adev->device.set_master_volume = adev_set_master_volume;
3756 adev->device.get_master_volume = adev_get_master_volume;
3757 adev->device.set_master_mute = adev_set_master_mute;
3758 adev->device.get_master_mute = adev_get_master_mute;
3759 adev->device.set_mode = adev_set_mode;
3760 adev->device.set_mic_mute = adev_set_mic_mute;
3761 adev->device.get_mic_mute = adev_get_mic_mute;
3762 adev->device.set_parameters = adev_set_parameters;
3763 adev->device.get_parameters = adev_get_parameters;
3764 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3765 adev->device.open_output_stream = adev_open_output_stream;
3766 adev->device.close_output_stream = adev_close_output_stream;
3767 adev->device.open_input_stream = adev_open_input_stream;
3768 adev->device.close_input_stream = adev_close_input_stream;
3769 adev->device.dump = adev_dump;
3770
3771 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003773 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003774 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003777 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003778 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003779 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003780 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003781 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003782 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003783 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303784
3785 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3786 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003788 adev->platform = platform_init(adev);
3789 if (!adev->platform) {
3790 free(adev->snd_dev_ref_cnt);
3791 free(adev);
3792 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3793 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003794 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003795 return -EINVAL;
3796 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003797
Naresh Tanniru4c630392014-05-12 01:05:52 +05303798 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3799
Eric Laurentc4aef752013-09-12 17:45:53 -07003800 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3801 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3802 if (adev->visualizer_lib == NULL) {
3803 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3804 } else {
3805 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3806 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003807 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003808 "visualizer_hal_start_output");
3809 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003810 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003811 "visualizer_hal_stop_output");
3812 }
3813 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003814 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003815 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003816
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003817 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3818 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3819 if (adev->offload_effects_lib == NULL) {
3820 ALOGE("%s: DLOPEN failed for %s", __func__,
3821 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3822 } else {
3823 ALOGV("%s: DLOPEN successful for %s", __func__,
3824 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3825 adev->offload_effects_start_output =
3826 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3827 "offload_effects_bundle_hal_start_output");
3828 adev->offload_effects_stop_output =
3829 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3830 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003831 adev->offload_effects_set_hpx_state =
3832 (int (*)(bool))dlsym(adev->offload_effects_lib,
3833 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303834 adev->offload_effects_get_parameters =
3835 (void (*)(struct str_parms *, struct str_parms *))
3836 dlsym(adev->offload_effects_lib,
3837 "offload_effects_bundle_get_parameters");
3838 adev->offload_effects_set_parameters =
3839 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3840 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003841 }
3842 }
3843
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003844 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3845 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3846 if (adev->adm_lib == NULL) {
3847 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3848 } else {
3849 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3850 adev->adm_init = (adm_init_t)
3851 dlsym(adev->adm_lib, "adm_init");
3852 adev->adm_deinit = (adm_deinit_t)
3853 dlsym(adev->adm_lib, "adm_deinit");
3854 adev->adm_register_input_stream = (adm_register_input_stream_t)
3855 dlsym(adev->adm_lib, "adm_register_input_stream");
3856 adev->adm_register_output_stream = (adm_register_output_stream_t)
3857 dlsym(adev->adm_lib, "adm_register_output_stream");
3858 adev->adm_deregister_stream = (adm_deregister_stream_t)
3859 dlsym(adev->adm_lib, "adm_deregister_stream");
3860 adev->adm_request_focus = (adm_request_focus_t)
3861 dlsym(adev->adm_lib, "adm_request_focus");
3862 adev->adm_abandon_focus = (adm_abandon_focus_t)
3863 dlsym(adev->adm_lib, "adm_abandon_focus");
3864 }
3865 }
3866
Mingming Yin514a8bc2014-07-29 15:22:21 -07003867 adev->bt_wb_speech_enabled = false;
3868
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003869 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 *device = &adev->device.common;
3871
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003872 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3873 &adev->streams_output_cfg_list);
3874
Kiran Kandi910e1862013-10-29 13:29:42 -07003875 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003876
3877 char value[PROPERTY_VALUE_MAX];
3878 int trial;
3879 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3880 trial = atoi(value);
3881 if (period_size_is_plausible_for_low_latency(trial)) {
3882 pcm_config_low_latency.period_size = trial;
3883 pcm_config_low_latency.start_threshold = trial / 4;
3884 pcm_config_low_latency.avail_min = trial / 4;
3885 configured_low_latency_capture_period_size = trial;
3886 }
3887 }
3888 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3889 trial = atoi(value);
3890 if (period_size_is_plausible_for_low_latency(trial)) {
3891 configured_low_latency_capture_period_size = trial;
3892 }
3893 }
3894
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003895 pthread_mutex_unlock(&adev_init_lock);
3896
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003897 if (adev->adm_init)
3898 adev->adm_data = adev->adm_init();
3899
Eric Laurent994a6932013-07-17 11:51:42 -07003900 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 return 0;
3902}
3903
3904static struct hw_module_methods_t hal_module_methods = {
3905 .open = adev_open,
3906};
3907
3908struct audio_module HAL_MODULE_INFO_SYM = {
3909 .common = {
3910 .tag = HARDWARE_MODULE_TAG,
3911 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3912 .hal_api_version = HARDWARE_HAL_API_VERSION,
3913 .id = AUDIO_HARDWARE_MODULE_ID,
3914 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003915 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916 .methods = &hal_module_methods,
3917 },
3918};