blob: c55cd139f34f5c77116d8bdcd286a5bd2b7ba71e [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",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -0700180 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
215#ifdef MULTIPLE_OFFLOAD_ENABLED
216 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
224#endif
225};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226
227#define STRING_TO_ENUM(string) { #string, string }
228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229struct string_to_enum {
230 const char *name;
231 uint32_t value;
232};
233
234static const struct string_to_enum out_channels_name_to_enum_table[] = {
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
242};
243
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700244static const struct string_to_enum out_formats_name_to_enum_table[] = {
245 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
247 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
248};
249
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700250static struct audio_device *adev = NULL;
251static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700252static unsigned int audio_device_ref_count;
253
Haynes Mathew George5191a852013-09-11 14:19:36 -0700254static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800256static int check_and_set_gapless_mode(struct audio_device *adev) {
257
258
259 char value[PROPERTY_VALUE_MAX] = {0};
260 bool gapless_enabled = false;
261 const char *mixer_ctl_name = "Compress Gapless Playback";
262 struct mixer_ctl *ctl;
263
264 ALOGV("%s:", __func__);
265 property_get("audio.offload.gapless.enabled", value, NULL);
266 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
267
268 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
269 if (!ctl) {
270 ALOGE("%s: Could not get ctl for mixer cmd - %s",
271 __func__, mixer_ctl_name);
272 return -EINVAL;
273 }
274
275 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
276 ALOGE("%s: Could not set gapless mode %d",
277 __func__, gapless_enabled);
278 return -EINVAL;
279 }
280 return 0;
281}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700282
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700283static bool is_supported_format(audio_format_t format)
284{
Eric Laurent86e17132013-09-12 17:49:30 -0700285 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530286 format == AUDIO_FORMAT_AAC_LC ||
287 format == AUDIO_FORMAT_AAC_HE_V1 ||
288 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangan93672f12015-08-24 20:30:31 +0530289 format == AUDIO_FORMAT_AAC_ADTS_LC ||
290 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
291 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800292 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700293 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530295 format == AUDIO_FORMAT_ALAC ||
296 format == AUDIO_FORMAT_APE ||
297 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800298 format == AUDIO_FORMAT_WMA ||
299 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800300 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301
302 return false;
303}
304
305static int get_snd_codec_id(audio_format_t format)
306{
307 int id = 0;
308
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700310 case AUDIO_FORMAT_MP3:
311 id = SND_AUDIOCODEC_MP3;
312 break;
313 case AUDIO_FORMAT_AAC:
314 id = SND_AUDIOCODEC_AAC;
315 break;
Manish Dewangan93672f12015-08-24 20:30:31 +0530316 case AUDIO_FORMAT_AAC_ADTS:
317 id = SND_AUDIOCODEC_AAC;
318 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530319 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800320 id = SND_AUDIOCODEC_PCM;
321 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700322 case AUDIO_FORMAT_FLAC:
323 id = SND_AUDIOCODEC_FLAC;
324 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530325 case AUDIO_FORMAT_ALAC:
326 id = SND_AUDIOCODEC_ALAC;
327 break;
328 case AUDIO_FORMAT_APE:
329 id = SND_AUDIOCODEC_APE;
330 break;
331 case AUDIO_FORMAT_VORBIS:
332 id = SND_AUDIOCODEC_VORBIS;
333 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800334 case AUDIO_FORMAT_WMA:
335 id = SND_AUDIOCODEC_WMA;
336 break;
337 case AUDIO_FORMAT_WMA_PRO:
338 id = SND_AUDIOCODEC_WMA_PRO;
339 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700340 default:
Mingming Yin90310102013-11-13 16:57:00 -0800341 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700342 }
343
344 return id;
345}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800346
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530347int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530348{
349 int snd_scard_state;
350
351 if (!adev)
352 return SND_CARD_STATE_OFFLINE;
353
354 pthread_mutex_lock(&adev->snd_card_status.lock);
355 snd_scard_state = adev->snd_card_status.state;
356 pthread_mutex_unlock(&adev->snd_card_status.lock);
357
358 return snd_scard_state;
359}
360
361static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
362{
363 if (!adev)
364 return -ENOSYS;
365
366 pthread_mutex_lock(&adev->snd_card_status.lock);
367 adev->snd_card_status.state = snd_scard_state;
368 pthread_mutex_unlock(&adev->snd_card_status.lock);
369
370 return 0;
371}
372
Avinash Vaish71a8b972014-07-24 15:36:33 +0530373static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
374 struct audio_usecase *uc_info)
375{
376 struct listnode *node;
377 struct audio_usecase *usecase;
378
379 if (uc_info == NULL)
380 return -EINVAL;
381
382 /* Re-route all voice usecases on the shared backend other than the
383 specified usecase to new snd devices */
384 list_for_each(node, &adev->usecase_list) {
385 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800386 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530387 enable_audio_route(adev, usecase);
388 }
389 return 0;
390}
391
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700392int pcm_ioctl(struct pcm *pcm, int request, ...)
393{
394 va_list ap;
395 void * arg;
396 int pcm_fd = *(int*)pcm;
397
398 va_start(ap, request);
399 arg = va_arg(ap, void *);
400 va_end(ap);
401
402 return ioctl(pcm_fd, request, arg);
403}
404
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700405int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700406 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800407{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700408 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700409 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800410
411 if (usecase == NULL)
412 return -EINVAL;
413
414 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
415
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800416 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700417 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800418 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700419 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800420
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800421#ifdef DS1_DOLBY_DAP_ENABLED
422 audio_extn_dolby_set_dmid(adev);
423 audio_extn_dolby_set_endpoint(adev);
424#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700425 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700426 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530427 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700428 audio_extn_utils_send_app_type_cfg(usecase);
Dhananjay Kumarcb419212015-08-28 13:24:16 +0530429 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800430 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530431 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700432 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700433 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434 ALOGV("%s: exit", __func__);
435 return 0;
436}
437
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700438int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700439 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800440{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700442 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530444 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 return -EINVAL;
446
447 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700448 if (usecase->type == PCM_CAPTURE)
449 snd_device = usecase->in_snd_device;
450 else
451 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800452 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530453 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700454 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700455 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700456 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530457 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 ALOGV("%s: exit", __func__);
459 return 0;
460}
461
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700462int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700463 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700465 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
466
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800467 if (snd_device < SND_DEVICE_MIN ||
468 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800469 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472
473 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474
475 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
476 ALOGE("%s: Invalid sound device returned", __func__);
477 return -EINVAL;
478 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700479 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700480 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700482 return 0;
483 }
484
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700485 if (audio_extn_spkr_prot_is_enabled())
486 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700487 /* start usb playback thread */
488 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
489 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
490 audio_extn_usb_start_playback(adev);
491
492 /* start usb capture thread */
493 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
494 audio_extn_usb_start_capture(adev);
495
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530496 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530497 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700499 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700500 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
501 adev->snd_dev_ref_cnt[snd_device]--;
502 return -EINVAL;
503 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200504 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800505 if (audio_extn_spkr_prot_start_processing(snd_device)) {
506 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200507 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800508 return -EINVAL;
509 }
510 } else {
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700511 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700512 /* due to the possibility of calibration overwrite between listen
513 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700518 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700519 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700520 audio_extn_sound_trigger_update_device_status(snd_device,
521 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530522 audio_extn_listen_update_device_status(snd_device,
523 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700524 return -EINVAL;
525 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300526 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700527 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529 return 0;
530}
531
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700532int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700533 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700535 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
536
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800537 if (snd_device < SND_DEVICE_MIN ||
538 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800539 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800540 return -EINVAL;
541 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
543 ALOGE("%s: device ref cnt is already 0", __func__);
544 return -EINVAL;
545 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700548
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
550 ALOGE("%s: Invalid sound device returned", __func__);
551 return -EINVAL;
552 }
553
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700555 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800556 /* exit usb play back thread */
557 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
558 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
559 audio_extn_usb_stop_playback();
560
561 /* exit usb capture thread */
562 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700563 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800564
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530565 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530566 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800567 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700568 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700569 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300570 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700571 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300572 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700573
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530574 if (snd_device == SND_DEVICE_OUT_HDMI)
575 adev->mChannelStatusSet = false;
576
Linux Build Service Account75e43952015-08-26 19:58:56 -0700577 if (snd_device == SND_DEVICE_OUT_HDMI)
578 adev->mChannelStatusSet = false;
579
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200580 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700581 audio_extn_sound_trigger_update_device_status(snd_device,
582 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530583 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800584 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800587 return 0;
588}
589
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590static void check_usecases_codec_backend(struct audio_device *adev,
591 struct audio_usecase *uc_info,
592 snd_device_t snd_device)
593{
594 struct listnode *node;
595 struct audio_usecase *usecase;
596 bool switch_device[AUDIO_USECASE_MAX];
597 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530598 int backend_idx = DEFAULT_CODEC_BACKEND;
599 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600
601 /*
602 * This function is to make sure that all the usecases that are active on
603 * the hardware codec backend are always routed to any one device that is
604 * handled by the hardware codec.
605 * For example, if low-latency and deep-buffer usecases are currently active
606 * on speaker and out_set_parameters(headset) is received on low-latency
607 * output, then we have to make sure deep-buffer is also switched to headset,
608 * because of the limitation that both the devices cannot be enabled
609 * at the same time as they share the same backend.
610 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700611 /*
612 * This call is to check if we need to force routing for a particular stream
613 * If there is a backend configuration change for the device when a
614 * new stream starts, then ADM needs to be closed and re-opened with the new
615 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530616 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700617 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530618 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
619 snd_device);
620 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700621 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800622 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800623 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700624 for (i = 0; i < AUDIO_USECASE_MAX; i++)
625 switch_device[i] = false;
626
627 list_for_each(node, &adev->usecase_list) {
628 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530629
630 if (usecase == uc_info)
631 continue;
632 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
633 ALOGV("%s: backend_idx: %d,"
634 "usecase_backend_idx: %d, curr device: %s, usecase device:"
635 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530636 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530637
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800638 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700639 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530640 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
641 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530642 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530643 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700644 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700645 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 switch_device[usecase->id] = true;
647 num_uc_to_switch++;
648 }
649 }
650
651 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700652 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530654 /* Make sure the previous devices to be disabled first and then enable the
655 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 list_for_each(node, &adev->usecase_list) {
657 usecase = node_to_item(node, struct audio_usecase, list);
658 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700659 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 }
661 }
662
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700663 list_for_each(node, &adev->usecase_list) {
664 usecase = node_to_item(node, struct audio_usecase, list);
665 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700666 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700667 }
668 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 /* Re-route all the usecases on the shared backend other than the
671 specified usecase to new snd devices */
672 list_for_each(node, &adev->usecase_list) {
673 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530674 /* Update the out_snd_device only before enabling the audio route */
675 if (switch_device[usecase->id] ) {
676 usecase->out_snd_device = snd_device;
677 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530678 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 }
680 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 }
682}
683
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700684static void check_and_route_capture_usecases(struct audio_device *adev,
685 struct audio_usecase *uc_info,
686 snd_device_t snd_device)
687{
688 struct listnode *node;
689 struct audio_usecase *usecase;
690 bool switch_device[AUDIO_USECASE_MAX];
691 int i, num_uc_to_switch = 0;
692
693 /*
694 * This function is to make sure that all the active capture usecases
695 * are always routed to the same input sound device.
696 * For example, if audio-record and voice-call usecases are currently
697 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
698 * is received for voice call then we have to make sure that audio-record
699 * usecase is also switched to earpiece i.e. voice-dmic-ef,
700 * because of the limitation that two devices cannot be enabled
701 * at the same time if they share the same backend.
702 */
703 for (i = 0; i < AUDIO_USECASE_MAX; i++)
704 switch_device[i] = false;
705
706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800708 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700709 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700710 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700711 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530712 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
713 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700714 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700715 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
716 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700717 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700718 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719 switch_device[usecase->id] = true;
720 num_uc_to_switch++;
721 }
722 }
723
724 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700725 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700726
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530727 /* Make sure the previous devices to be disabled first and then enable the
728 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700732 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800733 }
734 }
735
736 list_for_each(node, &adev->usecase_list) {
737 usecase = node_to_item(node, struct audio_usecase, list);
738 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700739 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700740 }
741 }
742
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743 /* Re-route all the usecases on the shared backend other than the
744 specified usecase to new snd devices */
745 list_for_each(node, &adev->usecase_list) {
746 usecase = node_to_item(node, struct audio_usecase, list);
747 /* Update the in_snd_device only before enabling the audio route */
748 if (switch_device[usecase->id] ) {
749 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800750 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530751 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700752 }
753 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 }
755}
756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800757/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700758static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800759{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700760 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700761 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800762
763 switch (channels) {
764 /*
765 * Do not handle stereo output in Multi-channel cases
766 * Stereo case is handled in normal playback path
767 */
768 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700769 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775 break;
776 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784 break;
785 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700786 ALOGE("HDMI does not support multi channel playback");
787 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800788 break;
789 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700790 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800791}
792
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800793audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
794 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795{
796 struct audio_usecase *usecase;
797 struct listnode *node;
798
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800801 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700802 ALOGV("%s: usecase id %d", __func__, usecase->id);
803 return usecase->id;
804 }
805 }
806 return USECASE_INVALID;
807}
808
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700809struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700810 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811{
812 struct audio_usecase *usecase;
813 struct listnode *node;
814
815 list_for_each(node, &adev->usecase_list) {
816 usecase = node_to_item(node, struct audio_usecase, list);
817 if (usecase->id == uc_id)
818 return usecase;
819 }
820 return NULL;
821}
822
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700823int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800825 snd_device_t out_snd_device = SND_DEVICE_NONE;
826 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 struct audio_usecase *usecase = NULL;
828 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800829 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800830 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800831 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800832 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 usecase = get_usecase_from_list(adev, uc_id);
836 if (usecase == NULL) {
837 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
838 return -EINVAL;
839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800841 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800842 (usecase->type == VOIP_CALL) ||
843 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700844 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800845 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700846 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 usecase->devices = usecase->stream.out->devices;
848 } else {
849 /*
850 * If the voice call is active, use the sound devices of voice call usecase
851 * so that it would not result any device switch. All the usecases will
852 * be switched to new device when select_devices() is called for voice call
853 * usecase. This is to avoid switching devices for voice call when
854 * check_usecases_codec_backend() is called below.
855 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700856 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700857 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800858 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
860 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 in_snd_device = vc_usecase->in_snd_device;
862 out_snd_device = vc_usecase->out_snd_device;
863 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800864 } else if (voice_extn_compress_voip_is_active(adev)) {
865 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700866 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530867 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700868 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800869 in_snd_device = voip_usecase->in_snd_device;
870 out_snd_device = voip_usecase->out_snd_device;
871 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800872 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800873 hfp_ucid = audio_extn_hfp_get_usecase();
874 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700875 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800876 in_snd_device = hfp_usecase->in_snd_device;
877 out_snd_device = hfp_usecase->out_snd_device;
878 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 }
880 if (usecase->type == PCM_PLAYBACK) {
881 usecase->devices = usecase->stream.out->devices;
882 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700883 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700884 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800885 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700886 if (usecase->stream.out == adev->primary_output &&
887 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800888 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700889 select_devices(adev, adev->active_input->usecase);
890 }
891 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 } else if (usecase->type == PCM_CAPTURE) {
893 usecase->devices = usecase->stream.in->device;
894 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700895 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700896 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530897 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
898 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
899 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
900 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700901 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -0700902 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700903 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
904 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700905 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700906 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700907 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 }
909 }
910
911 if (out_snd_device == usecase->out_snd_device &&
912 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 return 0;
914 }
915
sangwoobc677242013-08-08 16:53:43 +0900916 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700917 out_snd_device, platform_get_snd_device_name(out_snd_device),
918 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920 /*
921 * Limitation: While in call, to do a device switch we need to disable
922 * and enable both RX and TX devices though one of them is same as current
923 * device.
924 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700925 if ((usecase->type == VOICE_CALL) &&
926 (usecase->in_snd_device != SND_DEVICE_NONE) &&
927 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700928 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700929 }
930
931 if (((usecase->type == VOICE_CALL) ||
932 (usecase->type == VOIP_CALL)) &&
933 (usecase->out_snd_device != SND_DEVICE_NONE)) {
934 /* Disable sidetone only if voice/voip call already exists */
935 if (voice_is_call_state_active(adev) ||
936 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700937 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800938 }
939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 /* Disable current sound devices */
941 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700942 disable_audio_route(adev, usecase);
943 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 }
945
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700947 disable_audio_route(adev, usecase);
948 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800949 }
950
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800951 /* Applicable only on the targets that has external modem.
952 * New device information should be sent to modem before enabling
953 * the devices to reduce in-call device switch time.
954 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700955 if ((usecase->type == VOICE_CALL) &&
956 (usecase->in_snd_device != SND_DEVICE_NONE) &&
957 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800958 status = platform_switch_voice_call_enable_device_config(adev->platform,
959 out_snd_device,
960 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700961 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 /* Enable new sound devices */
964 if (out_snd_device != SND_DEVICE_NONE) {
965 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
966 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700967 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 }
969
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700970 if (in_snd_device != SND_DEVICE_NONE) {
971 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700972 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700973 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974
Avinash Vaish71a8b972014-07-24 15:36:33 +0530975 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700976 status = platform_switch_voice_call_device_post(adev->platform,
977 out_snd_device,
978 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530979 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700980 /* Enable sidetone only if voice/voip call already exists */
981 if (voice_is_call_state_active(adev) ||
982 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700983 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800985
sangwoo170731f2013-06-08 15:36:36 +0900986 usecase->in_snd_device = in_snd_device;
987 usecase->out_snd_device = out_snd_device;
988
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530989 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700990 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530991 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700992 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530993 usecase->stream.out->flags,
994 usecase->stream.out->format,
995 usecase->stream.out->sample_rate,
996 usecase->stream.out->bit_width,
997 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700998 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530999 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001000
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001001 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001002
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001003 /* Applicable only on the targets that has external modem.
1004 * Enable device command should be sent to modem only after
1005 * enabling voice call mixer controls
1006 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001007 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001008 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1009 out_snd_device,
1010 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301011 ALOGD("%s: done",__func__);
1012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 return status;
1014}
1015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016static int stop_input_stream(struct stream_in *in)
1017{
1018 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019 struct audio_usecase *uc_info;
1020 struct audio_device *adev = in->dev;
1021
Eric Laurentc8400632013-02-14 19:04:54 -08001022 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023
Eric Laurent994a6932013-07-17 11:51:42 -07001024 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001025 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 uc_info = get_usecase_from_list(adev, in->usecase);
1027 if (uc_info == NULL) {
1028 ALOGE("%s: Could not find the usecase (%d) in the list",
1029 __func__, in->usecase);
1030 return -EINVAL;
1031 }
1032
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001033 /* Close in-call recording streams */
1034 voice_check_and_stop_incall_rec_usecase(adev, in);
1035
Eric Laurent150dbfe2013-02-27 14:31:02 -08001036 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001037 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038
1039 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001040 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001042 list_remove(&uc_info->list);
1043 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044
Eric Laurent994a6932013-07-17 11:51:42 -07001045 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 return ret;
1047}
1048
1049int start_input_stream(struct stream_in *in)
1050{
1051 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001052 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053 struct audio_usecase *uc_info;
1054 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301055 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301057 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1058 if (get_usecase_from_list(adev, usecase) == NULL)
1059 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301060 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1061 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001062
Naresh Tanniru80659832014-06-04 18:17:56 +05301063
1064 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301065 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301066 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301067 goto error_config;
1068 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301069
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001070 /* Check if source matches incall recording usecase criteria */
1071 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1072 if (ret)
1073 goto error_config;
1074 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301075 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1076
1077 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1078 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1079 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1080 goto error_config;
1081 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001082
Eric Laurentb23d5282013-05-14 15:27:20 -07001083 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084 if (in->pcm_device_id < 0) {
1085 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1086 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001087 ret = -EINVAL;
1088 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090
1091 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001093
1094 if (!uc_info) {
1095 ret = -ENOMEM;
1096 goto error_config;
1097 }
1098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 uc_info->id = in->usecase;
1100 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001101 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 uc_info->devices = in->device;
1103 uc_info->in_snd_device = SND_DEVICE_NONE;
1104 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001106 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301107 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109
Eric Laurentc8400632013-02-14 19:04:54 -08001110 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001111 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1112
1113 unsigned int flags = PCM_IN;
1114 unsigned int pcm_open_retry_count = 0;
1115
1116 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1117 flags |= PCM_MMAP | PCM_NOIRQ;
1118 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1119 }
1120
1121 while (1) {
1122 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1123 flags, &in->config);
1124 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1125 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1126 if (in->pcm != NULL) {
1127 pcm_close(in->pcm);
1128 in->pcm = NULL;
1129 }
1130 if (pcm_open_retry_count-- == 0) {
1131 ret = -EIO;
1132 goto error_open;
1133 }
1134 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1135 continue;
1136 }
1137 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 }
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001139
1140 ALOGV("%s: pcm_prepare", __func__);
1141 ret = pcm_prepare(in->pcm);
1142 if (ret < 0) {
1143 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1144 pcm_close(in->pcm);
1145 in->pcm = NULL;
1146 goto error_open;
1147 }
1148
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301149 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301150
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001151 ALOGD("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001152
Eric Laurentc8400632013-02-14 19:04:54 -08001153 return ret;
1154
1155error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301157 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001158
1159error_config:
1160 adev->active_input = NULL;
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301161 /*
1162 * sleep 50ms to allow sufficient time for kernel
1163 * drivers to recover incases like SSR.
1164 */
1165 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001167
1168 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169}
1170
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001171void lock_input_stream(struct stream_in *in)
1172{
1173 pthread_mutex_lock(&in->pre_lock);
1174 pthread_mutex_lock(&in->lock);
1175 pthread_mutex_unlock(&in->pre_lock);
1176}
1177
1178void lock_output_stream(struct stream_out *out)
1179{
1180 pthread_mutex_lock(&out->pre_lock);
1181 pthread_mutex_lock(&out->lock);
1182 pthread_mutex_unlock(&out->pre_lock);
1183}
1184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001185/* must be called with out->lock locked */
1186static int send_offload_cmd_l(struct stream_out* out, int command)
1187{
1188 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1189
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001190 if (!cmd) {
1191 ALOGE("failed to allocate mem for command 0x%x", command);
1192 return -ENOMEM;
1193 }
1194
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001195 ALOGVV("%s %d", __func__, command);
1196
1197 cmd->cmd = command;
1198 list_add_tail(&out->offload_cmd_list, &cmd->node);
1199 pthread_cond_signal(&out->offload_cond);
1200 return 0;
1201}
1202
1203/* must be called iwth out->lock locked */
1204static void stop_compressed_output_l(struct stream_out *out)
1205{
1206 out->offload_state = OFFLOAD_STATE_IDLE;
1207 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001208 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001209 if (out->compr != NULL) {
1210 compress_stop(out->compr);
1211 while (out->offload_thread_blocked) {
1212 pthread_cond_wait(&out->cond, &out->lock);
1213 }
1214 }
1215}
1216
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001217bool is_offload_usecase(audio_usecase_t uc_id)
1218{
1219 unsigned int i;
1220 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1221 if (uc_id == offload_usecases[i])
1222 return true;
1223 }
1224 return false;
1225}
1226
1227static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1228{
1229 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1230 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1231 char value[PROPERTY_VALUE_MAX] = {0};
1232
1233 property_get("audio.offload.multiple.enabled", value, NULL);
1234 if (!(atoi(value) || !strncmp("true", value, 4)))
1235 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1236
1237 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1238 for (i = 0; i < num_usecase; i++) {
1239 if (!(adev->offload_usecases_state & (0x1<<i))) {
1240 adev->offload_usecases_state |= 0x1 << i;
1241 ret = offload_usecases[i];
1242 break;
1243 }
1244 }
1245 ALOGV("%s: offload usecase is %d", __func__, ret);
1246 return ret;
1247}
1248
1249static void free_offload_usecase(struct audio_device *adev,
1250 audio_usecase_t uc_id)
1251{
1252 unsigned int i;
1253 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1254 if (offload_usecases[i] == uc_id) {
1255 adev->offload_usecases_state &= ~(0x1<<i);
1256 break;
1257 }
1258 }
1259 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1260}
1261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001262static void *offload_thread_loop(void *context)
1263{
1264 struct stream_out *out = (struct stream_out *) context;
1265 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001266 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001268 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1269 set_sched_policy(0, SP_FOREGROUND);
1270 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1271
1272 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001273 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001274 for (;;) {
1275 struct offload_cmd *cmd = NULL;
1276 stream_callback_event_t event;
1277 bool send_callback = false;
1278
1279 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1280 __func__, list_empty(&out->offload_cmd_list),
1281 out->offload_state);
1282 if (list_empty(&out->offload_cmd_list)) {
1283 ALOGV("%s SLEEPING", __func__);
1284 pthread_cond_wait(&out->offload_cond, &out->lock);
1285 ALOGV("%s RUNNING", __func__);
1286 continue;
1287 }
1288
1289 item = list_head(&out->offload_cmd_list);
1290 cmd = node_to_item(item, struct offload_cmd, node);
1291 list_remove(item);
1292
1293 ALOGVV("%s STATE %d CMD %d out->compr %p",
1294 __func__, out->offload_state, cmd->cmd, out->compr);
1295
1296 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1297 free(cmd);
1298 break;
1299 }
1300
1301 if (out->compr == NULL) {
1302 ALOGE("%s: Compress handle is NULL", __func__);
1303 pthread_cond_signal(&out->cond);
1304 continue;
1305 }
1306 out->offload_thread_blocked = true;
1307 pthread_mutex_unlock(&out->lock);
1308 send_callback = false;
1309 switch(cmd->cmd) {
1310 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001311 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001313 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001314 send_callback = true;
1315 event = STREAM_CBK_EVENT_WRITE_READY;
1316 break;
1317 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001318 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301319 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001320 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301321 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001322 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301323 if (ret < 0)
1324 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301325 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301326 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001327 compress_drain(out->compr);
1328 else
1329 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301330 if (ret != -ENETRESET) {
1331 send_callback = true;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301332 pthread_mutex_lock(&out->lock);
1333 out->send_new_metadata = 1;
1334 out->send_next_track_params = true;
1335 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301336 event = STREAM_CBK_EVENT_DRAIN_READY;
1337 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1338 } else
1339 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001340 break;
1341 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001342 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001343 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001344 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001345 send_callback = true;
1346 event = STREAM_CBK_EVENT_DRAIN_READY;
1347 break;
1348 default:
1349 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1350 break;
1351 }
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001352 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001353 out->offload_thread_blocked = false;
1354 pthread_cond_signal(&out->cond);
vivek mehtacc70d4b2015-09-25 14:07:43 -07001355 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001356 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001357 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001358 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001359 free(cmd);
1360 }
1361
1362 pthread_cond_signal(&out->cond);
1363 while (!list_empty(&out->offload_cmd_list)) {
1364 item = list_head(&out->offload_cmd_list);
1365 list_remove(item);
1366 free(node_to_item(item, struct offload_cmd, node));
1367 }
1368 pthread_mutex_unlock(&out->lock);
1369
1370 return NULL;
1371}
1372
1373static int create_offload_callback_thread(struct stream_out *out)
1374{
1375 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1376 list_init(&out->offload_cmd_list);
1377 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1378 offload_thread_loop, out);
1379 return 0;
1380}
1381
1382static int destroy_offload_callback_thread(struct stream_out *out)
1383{
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001384 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001385 stop_compressed_output_l(out);
1386 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1387
1388 pthread_mutex_unlock(&out->lock);
1389 pthread_join(out->offload_thread, (void **) NULL);
1390 pthread_cond_destroy(&out->offload_cond);
1391
1392 return 0;
1393}
1394
Eric Laurent07eeafd2013-10-06 12:52:49 -07001395static bool allow_hdmi_channel_config(struct audio_device *adev)
1396{
1397 struct listnode *node;
1398 struct audio_usecase *usecase;
1399 bool ret = true;
1400
1401 list_for_each(node, &adev->usecase_list) {
1402 usecase = node_to_item(node, struct audio_usecase, list);
1403 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1404 /*
1405 * If voice call is already existing, do not proceed further to avoid
1406 * disabling/enabling both RX and TX devices, CSD calls, etc.
1407 * Once the voice call done, the HDMI channels can be configured to
1408 * max channels of remaining use cases.
1409 */
1410 if (usecase->id == USECASE_VOICE_CALL) {
1411 ALOGD("%s: voice call is active, no change in HDMI channels",
1412 __func__);
1413 ret = false;
1414 break;
1415 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1416 ALOGD("%s: multi channel playback is active, "
1417 "no change in HDMI channels", __func__);
1418 ret = false;
1419 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001420 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001421 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001422 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1423 ", no change in HDMI channels", __func__,
1424 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001425 ret = false;
1426 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001427 }
1428 }
1429 }
1430 return ret;
1431}
1432
1433static int check_and_set_hdmi_channels(struct audio_device *adev,
1434 unsigned int channels)
1435{
1436 struct listnode *node;
1437 struct audio_usecase *usecase;
1438
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001439 unsigned int supported_channels = platform_edid_get_max_channels(
1440 adev->platform);
1441 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001442 /* Check if change in HDMI channel config is allowed */
1443 if (!allow_hdmi_channel_config(adev))
1444 return 0;
1445
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001446 if (channels > supported_channels)
1447 channels = supported_channels;
1448
Eric Laurent07eeafd2013-10-06 12:52:49 -07001449 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001450 ALOGD("%s: Requested channels are same as current channels(%d)",
1451 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001452 return 0;
1453 }
1454
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001455 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001456 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001457 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001458 adev->cur_hdmi_channels = channels;
1459
1460 /*
1461 * Deroute all the playback streams routed to HDMI so that
1462 * the back end is deactivated. Note that backend will not
1463 * be deactivated if any one stream is connected to it.
1464 */
1465 list_for_each(node, &adev->usecase_list) {
1466 usecase = node_to_item(node, struct audio_usecase, list);
1467 if (usecase->type == PCM_PLAYBACK &&
1468 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001469 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001470 }
1471 }
1472
1473 /*
1474 * Enable all the streams disabled above. Now the HDMI backend
1475 * will be activated with new channel configuration
1476 */
1477 list_for_each(node, &adev->usecase_list) {
1478 usecase = node_to_item(node, struct audio_usecase, list);
1479 if (usecase->type == PCM_PLAYBACK &&
1480 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001481 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001482 }
1483 }
1484
1485 return 0;
1486}
1487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488static int stop_output_stream(struct stream_out *out)
1489{
1490 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 struct audio_usecase *uc_info;
1492 struct audio_device *adev = out->dev;
1493
Eric Laurent994a6932013-07-17 11:51:42 -07001494 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 uc_info = get_usecase_from_list(adev, out->usecase);
1497 if (uc_info == NULL) {
1498 ALOGE("%s: Could not find the usecase (%d) in the list",
1499 __func__, out->usecase);
1500 return -EINVAL;
1501 }
1502
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001503 if (is_offload_usecase(out->usecase) &&
1504 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001505 if (adev->visualizer_stop_output != NULL)
1506 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001507
1508 audio_extn_dts_remove_state_notifier_node(out->usecase);
1509
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001510 if (adev->offload_effects_stop_output != NULL)
1511 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1512 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001513
Eric Laurent150dbfe2013-02-27 14:31:02 -08001514 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001515 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516
1517 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001518 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001520 list_remove(&uc_info->list);
1521 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001523 if (is_offload_usecase(out->usecase) &&
1524 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1525 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1526 ALOGV("Disable passthrough , reset mixer to pcm");
1527 /* NO_PASSTHROUGH */
1528 out->compr_config.codec->compr_passthr = 0;
1529 audio_extn_dolby_set_hdmi_config(adev, out);
1530 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1531 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001532 /* Must be called after removing the usecase from list */
1533 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1534 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1535
Eric Laurent994a6932013-07-17 11:51:42 -07001536 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 return ret;
1538}
1539
1540int start_output_stream(struct stream_out *out)
1541{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001542 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001543 int sink_channels = 0;
1544 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 struct audio_usecase *uc_info;
1546 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301547 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001549 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1550 ret = -EINVAL;
1551 goto error_config;
1552 }
1553
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301554 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1555 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1556 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301557
Naresh Tanniru80659832014-06-04 18:17:56 +05301558 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301559 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301560 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301561 goto error_config;
1562 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301563
Eric Laurentb23d5282013-05-14 15:27:20 -07001564 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 if (out->pcm_device_id < 0) {
1566 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1567 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001568 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001569 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 }
1571
1572 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001573
1574 if (!uc_info) {
1575 ret = -ENOMEM;
1576 goto error_config;
1577 }
1578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 uc_info->id = out->usecase;
1580 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001581 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 uc_info->devices = out->devices;
1583 uc_info->in_snd_device = SND_DEVICE_NONE;
1584 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001585 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001586 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001587 if (is_offload_usecase(out->usecase)) {
1588 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001589 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1590 }
1591 }
Mingming Yin9c041392014-05-01 15:37:31 -07001592 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1593 if (!strncmp("true", prop_value, 4)) {
1594 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001595 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1596 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001597 check_and_set_hdmi_channels(adev, sink_channels);
1598 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001599 if (is_offload_usecase(out->usecase)) {
1600 unsigned int ch_count = out->compr_config.codec->ch_in;
1601 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1602 /* backend channel config for passthrough stream is stereo */
1603 ch_count = 2;
1604 check_and_set_hdmi_channels(adev, ch_count);
1605 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001606 check_and_set_hdmi_channels(adev, out->config.channels);
1607 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001608 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001609 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001610 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001612 select_devices(adev, out->usecase);
1613
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001614 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1615 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001616 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001617 unsigned int flags = PCM_OUT;
1618 unsigned int pcm_open_retry_count = 0;
1619 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1620 flags |= PCM_MMAP | PCM_NOIRQ;
1621 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1622 } else
1623 flags |= PCM_MONOTONIC;
1624
1625 while (1) {
1626 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1627 flags, &out->config);
1628 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1629 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1630 if (out->pcm != NULL) {
1631 pcm_close(out->pcm);
1632 out->pcm = NULL;
1633 }
1634 if (pcm_open_retry_count-- == 0) {
1635 ret = -EIO;
1636 goto error_open;
1637 }
1638 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1639 continue;
1640 }
1641 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001642 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001643
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001644 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1645 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001646
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001647 ALOGV("%s: pcm_prepare", __func__);
1648 if (pcm_is_ready(out->pcm)) {
1649 ret = pcm_prepare(out->pcm);
1650 if (ret < 0) {
1651 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1652 pcm_close(out->pcm);
1653 out->pcm = NULL;
1654 goto error_open;
1655 }
1656 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001658 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1659 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001661 out->compr = compress_open(adev->snd_card,
1662 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001663 COMPRESS_IN, &out->compr_config);
1664 if (out->compr && !is_compress_ready(out->compr)) {
1665 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1666 compress_close(out->compr);
1667 out->compr = NULL;
1668 ret = -EIO;
1669 goto error_open;
1670 }
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301671 /* compress_open sends params of the track, so reset the flag here */
1672 out->is_compr_metadata_avail = false;
1673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001674 if (out->offload_callback)
1675 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001676
Fred Oh3f43e742015-03-04 18:42:34 -08001677 /* Since small bufs uses blocking writes, a write will be blocked
1678 for the default max poll time (20s) in the event of an SSR.
1679 Reduce the poll time to observe and deal with SSR faster.
1680 */
1681 if (out->use_small_bufs) {
1682 compress_set_max_poll_wait(out->compr, 1000);
1683 }
1684
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001685 audio_extn_dts_create_state_notifier_node(out->usecase);
1686 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1687 popcount(out->channel_mask),
1688 out->playback_started);
1689
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001690#ifdef DS1_DOLBY_DDP_ENABLED
1691 if (audio_extn_is_dolby_format(out->format))
1692 audio_extn_dolby_send_ddp_endp_params(adev);
1693#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001694 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1695 if (adev->visualizer_start_output != NULL)
1696 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1697 if (adev->offload_effects_start_output != NULL)
1698 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001699 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001702
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001703 ALOGD("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001706error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001708error_config:
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301709 /*
1710 * sleep 50ms to allow sufficient time for kernel
1711 * drivers to recover incases like SSR.
1712 */
1713 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001714 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715}
1716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717static int check_input_parameters(uint32_t sample_rate,
1718 audio_format_t format,
1719 int channel_count)
1720{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001721 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001723 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001724 !voice_extn_compress_voip_is_format_supported(format) &&
1725 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001726
1727 switch (channel_count) {
1728 case 1:
1729 case 2:
1730 case 6:
1731 break;
1732 default:
1733 ret = -EINVAL;
1734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735
1736 switch (sample_rate) {
1737 case 8000:
1738 case 11025:
1739 case 12000:
1740 case 16000:
1741 case 22050:
1742 case 24000:
1743 case 32000:
1744 case 44100:
1745 case 48000:
1746 break;
1747 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001748 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 }
1750
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001751 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752}
1753
1754static size_t get_input_buffer_size(uint32_t sample_rate,
1755 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001756 int channel_count,
1757 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758{
1759 size_t size = 0;
1760
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001761 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1762 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001764 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001765 if (is_low_latency)
1766 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001767 /* ToDo: should use frame_size computed based on the format and
1768 channel_count here. */
1769 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001771 /* make sure the size is multiple of 32 bytes
1772 * At 48 kHz mono 16-bit PCM:
1773 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1774 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1775 */
1776 size += 0x1f;
1777 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001778
1779 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780}
1781
1782static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1783{
1784 struct stream_out *out = (struct stream_out *)stream;
1785
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787}
1788
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001789static int out_set_sample_rate(struct audio_stream *stream __unused,
1790 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791{
1792 return -ENOSYS;
1793}
1794
1795static size_t out_get_buffer_size(const struct audio_stream *stream)
1796{
1797 struct stream_out *out = (struct stream_out *)stream;
1798
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001799 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001801 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1802 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001804 return out->config.period_size *
1805 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806}
1807
1808static uint32_t out_get_channels(const struct audio_stream *stream)
1809{
1810 struct stream_out *out = (struct stream_out *)stream;
1811
1812 return out->channel_mask;
1813}
1814
1815static audio_format_t out_get_format(const struct audio_stream *stream)
1816{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 struct stream_out *out = (struct stream_out *)stream;
1818
1819 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820}
1821
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001822static int out_set_format(struct audio_stream *stream __unused,
1823 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824{
1825 return -ENOSYS;
1826}
1827
1828static int out_standby(struct audio_stream *stream)
1829{
1830 struct stream_out *out = (struct stream_out *)stream;
1831 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301833 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1834 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001835 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1836 /* Ignore standby in case of voip call because the voip output
1837 * stream is closed in adev_close_output_stream()
1838 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301839 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001840 return 0;
1841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001843 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001845 if (adev->adm_deregister_stream)
1846 adev->adm_deregister_stream(adev->adm_data, out->handle);
1847
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001848 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001850 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001851 if (out->pcm) {
1852 pcm_close(out->pcm);
1853 out->pcm = NULL;
1854 }
1855 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001856 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001857 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301858 out->send_next_track_params = false;
1859 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 out->gapless_mdata.encoder_delay = 0;
1861 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001862 if (out->compr != NULL) {
1863 compress_close(out->compr);
1864 out->compr = NULL;
1865 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001866 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001868 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 }
1870 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001871 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872 return 0;
1873}
1874
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001875static int out_dump(const struct audio_stream *stream __unused,
1876 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877{
1878 return 0;
1879}
1880
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001881static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1882{
1883 int ret = 0;
1884 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001885
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001886 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001887 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001888 return -EINVAL;
1889 }
1890
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301891 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001892
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001893 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1894 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301895 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001896 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001897 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1898 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301899 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001900 }
1901
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001902 ALOGV("%s new encoder delay %u and padding %u", __func__,
1903 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1904
1905 return 0;
1906}
1907
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001908static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1909{
1910 return out == adev->primary_output || out == adev->voice_tx_output;
1911}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1914{
1915 struct stream_out *out = (struct stream_out *)stream;
1916 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001917 struct audio_usecase *usecase;
1918 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919 struct str_parms *parms;
1920 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001921 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001922 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923
sangwoobc677242013-08-08 16:53:43 +09001924 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301927 if (!parms)
1928 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001929 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1930 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 val = atoi(value);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001932 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001933 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001935 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301936 * When HDMI cable is unplugged/usb hs is disconnected the
1937 * music playback is paused and the policy manager sends routing=0
1938 * But the audioflingercontinues to write data until standby time
1939 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 * Avoid this by routing audio to speaker until standby.
1941 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301942 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1943 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001944 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001945 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1946 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 }
1948
1949 /*
1950 * select_devices() call below switches all the usecases on the same
1951 * backend to the new device. Refer to check_usecases_codec_backend() in
1952 * the select_devices(). But how do we undo this?
1953 *
1954 * For example, music playback is active on headset (deep-buffer usecase)
1955 * and if we go to ringtones and select a ringtone, low-latency usecase
1956 * will be started on headset+speaker. As we can't enable headset+speaker
1957 * and headset devices at the same time, select_devices() switches the music
1958 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1959 * So when the ringtone playback is completed, how do we undo the same?
1960 *
1961 * We are relying on the out_set_parameters() call on deep-buffer output,
1962 * once the ringtone playback is ended.
1963 * NOTE: We should not check if the current devices are same as new devices.
1964 * Because select_devices() must be called to switch back the music
1965 * playback to headset.
1966 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001967 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001968 out->devices = val;
1969
1970 if (!out->standby)
1971 select_devices(adev, out->usecase);
1972
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001973 if (output_drives_call(adev, out)) {
1974 if(!voice_is_in_call(adev)) {
1975 if (adev->mode == AUDIO_MODE_IN_CALL) {
1976 adev->current_call_output = out;
1977 ret = voice_start_call(adev);
1978 }
1979 } else {
1980 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001981 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001982 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001983 }
1984 }
1985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001987 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001989
1990 if (out == adev->primary_output) {
1991 pthread_mutex_lock(&adev->lock);
1992 audio_extn_set_parameters(adev, parms);
1993 pthread_mutex_unlock(&adev->lock);
1994 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001995 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001996 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001997 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001998
1999 audio_extn_dts_create_state_notifier_node(out->usecase);
2000 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2001 popcount(out->channel_mask),
2002 out->playback_started);
2003
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002004 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002005 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302008error:
Eric Laurent994a6932013-07-17 11:51:42 -07002009 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 return ret;
2011}
2012
2013static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2014{
2015 struct stream_out *out = (struct stream_out *)stream;
2016 struct str_parms *query = str_parms_create_str(keys);
2017 char *str;
2018 char value[256];
2019 struct str_parms *reply = str_parms_create();
2020 size_t i, j;
2021 int ret;
2022 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002023
2024 if (!query || !reply) {
2025 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2026 return NULL;
2027 }
2028
Eric Laurent994a6932013-07-17 11:51:42 -07002029 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2031 if (ret >= 0) {
2032 value[0] = '\0';
2033 i = 0;
2034 while (out->supported_channel_masks[i] != 0) {
2035 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2036 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2037 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002038 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002040 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 first = false;
2042 break;
2043 }
2044 }
2045 i++;
2046 }
2047 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2048 str = str_parms_to_str(reply);
2049 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002050 voice_extn_out_get_parameters(out, query, reply);
2051 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002052 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002053 free(str);
2054 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002055 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002057
2058 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2059 if (ret >= 0) {
2060 value[0] = '\0';
2061 i = 0;
2062 first = true;
2063 while (out->supported_formats[i] != 0) {
2064 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2065 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2066 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002067 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002068 }
2069 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2070 first = false;
2071 break;
2072 }
2073 }
2074 i++;
2075 }
2076 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2077 str = str_parms_to_str(reply);
2078 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 str_parms_destroy(query);
2080 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002081 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 return str;
2083}
2084
2085static uint32_t out_get_latency(const struct audio_stream_out *stream)
2086{
2087 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002088 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089
Alexy Josephaa54c872014-12-03 02:46:47 -08002090 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002091 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002092 } else {
2093 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002095 }
2096
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302097 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002098 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099}
2100
2101static int out_set_volume(struct audio_stream_out *stream, float left,
2102 float right)
2103{
Eric Laurenta9024de2013-04-04 09:19:12 -07002104 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105 int volume[2];
2106
Eric Laurenta9024de2013-04-04 09:19:12 -07002107 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2108 /* only take left channel into account: the API is for stereo anyway */
2109 out->muted = (left == 0.0f);
2110 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002111 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002112 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2113 /*
2114 * Set mute or umute on HDMI passthrough stream.
2115 * Only take left channel into account.
2116 * Mute is 0 and unmute 1
2117 */
2118 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2119 } else {
2120 char mixer_ctl_name[128];
2121 struct audio_device *adev = out->dev;
2122 struct mixer_ctl *ctl;
2123 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002124 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002126 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2127 "Compress Playback %d Volume", pcm_device_id);
2128 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2129 if (!ctl) {
2130 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2131 __func__, mixer_ctl_name);
2132 return -EINVAL;
2133 }
2134 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2135 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2136 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2137 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002139 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 return -ENOSYS;
2142}
2143
2144static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2145 size_t bytes)
2146{
2147 struct stream_out *out = (struct stream_out *)stream;
2148 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302149 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002150 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002152 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302153
Naresh Tanniru80659832014-06-04 18:17:56 +05302154 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002155 // increase written size during SSR to avoid mismatch
2156 // with the written frames count in AF
2157 if (!is_offload_usecase(out->usecase))
2158 out->written += bytes / (out->config.channels * sizeof(short));
2159
Naresh Tanniru80659832014-06-04 18:17:56 +05302160 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302161 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302162 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302163 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002164 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302165 //during SSR for compress usecase we should return error to flinger
2166 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2167 pthread_mutex_unlock(&out->lock);
2168 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302169 }
2170 }
2171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002173 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002174 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002175 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2176 ret = voice_extn_compress_voip_start_output_stream(out);
2177 else
2178 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002179 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002182 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 goto exit;
2184 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002185 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2186 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302189 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2190 setChannelStatus(out, buffer, bytes);
2191 adev->mChannelStatusSet = true;
2192 }
2193
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002194 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002195 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002196 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002197 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002198 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2199 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302200 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2201 ALOGD("copl(%p):send next track params in gapless", out);
2202 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2203 out->send_next_track_params = false;
2204 out->is_compr_metadata_avail = false;
2205 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002206 }
2207
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302209 if (ret < 0)
2210 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002211 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002212 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302213 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302215 } else if (-ENETRESET == ret) {
2216 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2217 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2218 pthread_mutex_unlock(&out->lock);
2219 out_standby(&out->stream.common);
2220 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002224 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 out->playback_started = 1;
2226 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002227
2228 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2229 popcount(out->channel_mask),
2230 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 }
2232 pthread_mutex_unlock(&out->lock);
2233 return ret;
2234 } else {
2235 if (out->pcm) {
2236 if (out->muted)
2237 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002240
2241 if (adev->adm_request_focus)
2242 adev->adm_request_focus(adev->adm_data, out->handle);
2243
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002244 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2245 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2246 else
2247 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002248
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302249 if (ret < 0)
2250 ret = -errno;
2251 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002252 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002253
2254 if (adev->adm_abandon_focus)
2255 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 }
2258
2259exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302260 /* ToDo: There may be a corner case when SSR happens back to back during
2261 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302262 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302263 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302264 }
2265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266 pthread_mutex_unlock(&out->lock);
2267
2268 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002269 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002270 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302271 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302272 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302273 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302274 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302275 out->standby = true;
2276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002278 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302279 out_get_sample_rate(&out->stream.common));
2280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 }
2282 return bytes;
2283}
2284
2285static int out_get_render_position(const struct audio_stream_out *stream,
2286 uint32_t *dsp_frames)
2287{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302289 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002290
2291 if (dsp_frames == NULL)
2292 return -EINVAL;
2293
2294 *dsp_frames = 0;
2295 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002296 ssize_t ret = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002297 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302299 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302301 if (ret < 0)
2302 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002303 ALOGVV("%s rendered frames %d sample_rate %d",
2304 __func__, *dsp_frames, out->sample_rate);
2305 }
2306 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302307 if (-ENETRESET == ret) {
2308 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2309 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2310 return -EINVAL;
2311 } else if(ret < 0) {
2312 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2313 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302314 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2315 /*
2316 * Handle corner case where compress session is closed during SSR
2317 * and timestamp is queried
2318 */
2319 ALOGE(" ERROR: sound card not active, return error");
2320 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302321 } else {
2322 return 0;
2323 }
Zhou Song32a556e2015-05-05 10:46:56 +08002324 } else if (audio_is_linear_pcm(out->format)) {
2325 *dsp_frames = out->written;
2326 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327 } else
2328 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329}
2330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002331static int out_add_audio_effect(const struct audio_stream *stream __unused,
2332 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 return 0;
2335}
2336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002337static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2338 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339{
2340 return 0;
2341}
2342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002343static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2344 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345{
2346 return -EINVAL;
2347}
2348
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002349static int out_get_presentation_position(const struct audio_stream_out *stream,
2350 uint64_t *frames, struct timespec *timestamp)
2351{
2352 struct stream_out *out = (struct stream_out *)stream;
2353 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002354 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002355
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002356 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002357
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002358 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002359 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302360 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002361 &out->sample_rate);
2362 ALOGVV("%s rendered frames %ld sample_rate %d",
2363 __func__, dsp_frames, out->sample_rate);
2364 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302365 if (ret < 0)
2366 ret = -errno;
2367 if (-ENETRESET == ret) {
2368 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2369 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2370 ret = -EINVAL;
2371 } else
2372 ret = 0;
2373
Eric Laurent949a0892013-09-20 09:20:13 -07002374 /* this is the best we can do */
2375 clock_gettime(CLOCK_MONOTONIC, timestamp);
2376 }
2377 } else {
2378 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002379 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002380 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2381 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002382 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002383 // This adjustment accounts for buffering after app processor.
2384 // It is based on estimated DSP latency per use case, rather than exact.
2385 signed_frames -=
2386 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2387
Eric Laurent949a0892013-09-20 09:20:13 -07002388 // It would be unusual for this value to be negative, but check just in case ...
2389 if (signed_frames >= 0) {
2390 *frames = signed_frames;
2391 ret = 0;
2392 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002393 }
2394 }
2395 }
2396
2397 pthread_mutex_unlock(&out->lock);
2398
2399 return ret;
2400}
2401
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402static int out_set_callback(struct audio_stream_out *stream,
2403 stream_callback_t callback, void *cookie)
2404{
2405 struct stream_out *out = (struct stream_out *)stream;
2406
2407 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002408 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 out->offload_callback = callback;
2410 out->offload_cookie = cookie;
2411 pthread_mutex_unlock(&out->lock);
2412 return 0;
2413}
2414
2415static int out_pause(struct audio_stream_out* stream)
2416{
2417 struct stream_out *out = (struct stream_out *)stream;
2418 int status = -ENOSYS;
2419 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002420 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002421 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002422 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302424 struct audio_device *adev = out->dev;
2425 int snd_scard_state = get_snd_card_state(adev);
2426
2427 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2428 status = compress_pause(out->compr);
2429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002431
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302432 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002433 audio_extn_dts_notify_playback_state(out->usecase, 0,
2434 out->sample_rate, popcount(out->channel_mask),
2435 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 }
2437 pthread_mutex_unlock(&out->lock);
2438 }
2439 return status;
2440}
2441
2442static int out_resume(struct audio_stream_out* stream)
2443{
2444 struct stream_out *out = (struct stream_out *)stream;
2445 int status = -ENOSYS;
2446 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002447 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002448 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 status = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002450 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302452 struct audio_device *adev = out->dev;
2453 int snd_scard_state = get_snd_card_state(adev);
2454
2455 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2456 status = compress_resume(out->compr);
2457
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002459
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302460 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002461 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2462 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 }
2464 pthread_mutex_unlock(&out->lock);
2465 }
2466 return status;
2467}
2468
2469static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2470{
2471 struct stream_out *out = (struct stream_out *)stream;
2472 int status = -ENOSYS;
2473 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002474 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002475 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002476 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2477 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2478 else
2479 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2480 pthread_mutex_unlock(&out->lock);
2481 }
2482 return status;
2483}
2484
2485static int out_flush(struct audio_stream_out* stream)
2486{
2487 struct stream_out *out = (struct stream_out *)stream;
2488 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002489 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002490 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002491 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002492 stop_compressed_output_l(out);
2493 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002494 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002495 return 0;
2496 }
2497 return -ENOSYS;
2498}
2499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500/** audio_stream_in implementation **/
2501static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2502{
2503 struct stream_in *in = (struct stream_in *)stream;
2504
2505 return in->config.rate;
2506}
2507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002508static int in_set_sample_rate(struct audio_stream *stream __unused,
2509 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510{
2511 return -ENOSYS;
2512}
2513
2514static size_t in_get_buffer_size(const struct audio_stream *stream)
2515{
2516 struct stream_in *in = (struct stream_in *)stream;
2517
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002518 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2519 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002520 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2521 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002522
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002523 return in->config.period_size *
2524 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525}
2526
2527static uint32_t in_get_channels(const struct audio_stream *stream)
2528{
2529 struct stream_in *in = (struct stream_in *)stream;
2530
2531 return in->channel_mask;
2532}
2533
2534static audio_format_t in_get_format(const struct audio_stream *stream)
2535{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002536 struct stream_in *in = (struct stream_in *)stream;
2537
2538 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539}
2540
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002541static int in_set_format(struct audio_stream *stream __unused,
2542 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543{
2544 return -ENOSYS;
2545}
2546
2547static int in_standby(struct audio_stream *stream)
2548{
2549 struct stream_in *in = (struct stream_in *)stream;
2550 struct audio_device *adev = in->dev;
2551 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302552 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2553 stream, in->usecase, use_case_table[in->usecase]);
2554
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002555 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2556 /* Ignore standby in case of voip call because the voip input
2557 * stream is closed in adev_close_input_stream()
2558 */
2559 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2560 return status;
2561 }
2562
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002563 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002564 if (!in->standby && in->is_st_session) {
2565 ALOGD("%s: sound trigger pcm stop lab", __func__);
2566 audio_extn_sound_trigger_stop_lab(in);
2567 in->standby = 1;
2568 }
2569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002571 if (adev->adm_deregister_stream)
2572 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2573
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002574 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002576 if (in->pcm) {
2577 pcm_close(in->pcm);
2578 in->pcm = NULL;
2579 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002581 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 }
2583 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002584 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 return status;
2586}
2587
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002588static int in_dump(const struct audio_stream *stream __unused,
2589 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590{
2591 return 0;
2592}
2593
2594static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2595{
2596 struct stream_in *in = (struct stream_in *)stream;
2597 struct audio_device *adev = in->dev;
2598 struct str_parms *parms;
2599 char *str;
2600 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002601 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302603 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 parms = str_parms_create_str(kvpairs);
2605
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302606 if (!parms)
2607 goto error;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002608 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002609 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002610
2611 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2612 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 val = atoi(value);
2614 /* no audio source uses val == 0 */
2615 if ((in->source != val) && (val != 0)) {
2616 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002617 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2618 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2619 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2620 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002621 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002622 err = voice_extn_compress_voip_open_input_stream(in);
2623 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002624 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002625 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002626 }
2627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 }
2629 }
2630
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002631 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2632 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002634 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 in->device = val;
2636 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002637 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002638 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 }
2640 }
2641
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002642done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002644 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
2646 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302647error:
Eric Laurent994a6932013-07-17 11:51:42 -07002648 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 return ret;
2650}
2651
2652static char* in_get_parameters(const struct audio_stream *stream,
2653 const char *keys)
2654{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002655 struct stream_in *in = (struct stream_in *)stream;
2656 struct str_parms *query = str_parms_create_str(keys);
2657 char *str;
2658 char value[256];
2659 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002660
2661 if (!query || !reply) {
2662 ALOGE("in_get_parameters: failed to create query or reply");
2663 return NULL;
2664 }
2665
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002666 ALOGV("%s: enter: keys - %s", __func__, keys);
2667
2668 voice_extn_in_get_parameters(in, query, reply);
2669
2670 str = str_parms_to_str(reply);
2671 str_parms_destroy(query);
2672 str_parms_destroy(reply);
2673
2674 ALOGV("%s: exit: returns - %s", __func__, str);
2675 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676}
2677
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002678static int in_set_gain(struct audio_stream_in *stream __unused,
2679 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680{
2681 return 0;
2682}
2683
2684static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2685 size_t bytes)
2686{
2687 struct stream_in *in = (struct stream_in *)stream;
2688 struct audio_device *adev = in->dev;
2689 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302690 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002692 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302693
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002694 if (in->is_st_session) {
2695 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2696 /* Read from sound trigger HAL */
2697 audio_extn_sound_trigger_read(in, buffer, bytes);
2698 pthread_mutex_unlock(&in->lock);
2699 return bytes;
2700 }
2701
2702 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2703 ALOGD(" %s: sound card is not active/SSR state", __func__);
2704 ret= -EIO;;
2705 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302706 }
2707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002709 pthread_mutex_lock(&adev->lock);
2710 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2711 ret = voice_extn_compress_voip_start_input_stream(in);
2712 else
2713 ret = start_input_stream(in);
2714 pthread_mutex_unlock(&adev->lock);
2715 if (ret != 0) {
2716 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 }
2718 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002719 if (adev->adm_register_input_stream)
2720 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722
Naresh Tanniru4a080142015-06-15 10:35:19 -07002723 if (adev->adm_request_focus)
2724 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002727 if (audio_extn_ssr_get_enabled() &&
2728 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002729 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002730 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2731 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002732 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2733 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002734 else
2735 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302736 if (ret < 0)
2737 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 }
2739
Naresh Tanniru4a080142015-06-15 10:35:19 -07002740 if (adev->adm_abandon_focus)
2741 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 /*
2744 * Instead of writing zeroes here, we could trust the hardware
2745 * to always provide zeroes when muted.
2746 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302747 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2748 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 memset(buffer, 0, bytes);
2750
2751exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302752 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302753 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002754 if (-ENETRESET == ret)
2755 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 pthread_mutex_unlock(&in->lock);
2758
2759 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302760 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302761 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302762 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302763 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302764 in->standby = true;
2765 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302766 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002768 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002769 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302770 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 }
2772 return bytes;
2773}
2774
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002775static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776{
2777 return 0;
2778}
2779
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002780static int add_remove_audio_effect(const struct audio_stream *stream,
2781 effect_handle_t effect,
2782 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002784 struct stream_in *in = (struct stream_in *)stream;
2785 int status = 0;
2786 effect_descriptor_t desc;
2787
2788 status = (*effect)->get_descriptor(effect, &desc);
2789 if (status != 0)
2790 return status;
2791
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002792 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002793 pthread_mutex_lock(&in->dev->lock);
2794 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2795 in->enable_aec != enable &&
2796 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2797 in->enable_aec = enable;
2798 if (!in->standby)
2799 select_devices(in->dev, in->usecase);
2800 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002801 if (in->enable_ns != enable &&
2802 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2803 in->enable_ns = enable;
2804 if (!in->standby)
2805 select_devices(in->dev, in->usecase);
2806 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002807 pthread_mutex_unlock(&in->dev->lock);
2808 pthread_mutex_unlock(&in->lock);
2809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 return 0;
2811}
2812
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002813static int in_add_audio_effect(const struct audio_stream *stream,
2814 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815{
Eric Laurent994a6932013-07-17 11:51:42 -07002816 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002817 return add_remove_audio_effect(stream, effect, true);
2818}
2819
2820static int in_remove_audio_effect(const struct audio_stream *stream,
2821 effect_handle_t effect)
2822{
Eric Laurent994a6932013-07-17 11:51:42 -07002823 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002824 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825}
2826
2827static int adev_open_output_stream(struct audio_hw_device *dev,
2828 audio_io_handle_t handle,
2829 audio_devices_t devices,
2830 audio_output_flags_t flags,
2831 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002832 struct audio_stream_out **stream_out,
2833 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834{
2835 struct audio_device *adev = (struct audio_device *)dev;
2836 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002837 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002838 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302841
2842 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2843 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2844 ALOGE(" sound card is not active rejecting compress output open request");
2845 return -EINVAL;
2846 }
2847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2849
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302850 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2851 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2852 devices, flags, &out->stream);
2853
2854
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002855 if (!out) {
2856 return -ENOMEM;
2857 }
2858
Haynes Mathew George204045b2015-02-25 20:32:03 -08002859 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002860 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002861 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 if (devices == AUDIO_DEVICE_NONE)
2864 devices = AUDIO_DEVICE_OUT_SPEAKER;
2865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866 out->flags = flags;
2867 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002868 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002869 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->sample_rate = config->sample_rate;
2871 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2872 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002873 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002874 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002875 out->non_blocking = 0;
2876 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302878 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2879 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002880 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2881 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2882
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002883 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002884 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2885 ret = read_hdmi_channel_masks(out);
2886
2887 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2888 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002889 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002890 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002891 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002892
2893 if (config->sample_rate == 0)
2894 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2895 if (config->channel_mask == 0)
2896 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2897
2898 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2901 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002903 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002905 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2906 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002907 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002908 ret = voice_extn_compress_voip_open_output_stream(out);
2909 if (ret != 0) {
2910 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2911 __func__, ret);
2912 goto error_open;
2913 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2915 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2916 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2917 ALOGE("%s: Unsupported Offload information", __func__);
2918 ret = -EINVAL;
2919 goto error_open;
2920 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002921
2922 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2923 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2924 ALOGV("read and update_pass through formats");
2925 ret = audio_extn_dolby_update_passt_formats(adev, out);
2926 if(ret != 0) {
2927 goto error_open;
2928 }
2929 if(config->offload_info.format == 0)
2930 config->offload_info.format = out->supported_formats[0];
2931 }
2932
Mingming Yin90310102013-11-13 16:57:00 -08002933 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002934 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 ALOGE("%s: Unsupported audio format", __func__);
2936 ret = -EINVAL;
2937 goto error_open;
2938 }
2939
2940 out->compr_config.codec = (struct snd_codec *)
2941 calloc(1, sizeof(struct snd_codec));
2942
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002943 if (!out->compr_config.codec) {
2944 ret = -ENOMEM;
2945 goto error_open;
2946 }
2947
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002948 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949 if (config->offload_info.channel_mask)
2950 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002951 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002953 config->offload_info.channel_mask = config->channel_mask;
2954 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002955 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 out->sample_rate = config->offload_info.sample_rate;
2957
2958 out->stream.set_callback = out_set_callback;
2959 out->stream.pause = out_pause;
2960 out->stream.resume = out_resume;
2961 out->stream.drain = out_drain;
2962 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002963 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002964
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002965 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002966 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002967 audio_extn_dolby_get_snd_codec_id(adev, out,
2968 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002969 else
2970 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302972 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002973 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002974 platform_get_pcm_offload_buffer_size(&config->offload_info);
2975 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2976 out->compr_config.fragment_size =
2977 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002978 } else {
2979 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002980 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002981 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2983 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002984 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002985 out->compr_config.codec->bit_rate =
2986 config->offload_info.bit_rate;
2987 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002988 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002989 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302990 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002991 /*TODO: Do we need to change it for passthrough */
2992 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002993
Manish Dewangan93672f12015-08-24 20:30:31 +05302994 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2995 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2996 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2997 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002998 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2999 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003000 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003001 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3002
Mingming Yin3ee55c62014-08-04 14:23:35 -07003003 if (out->bit_width == 24) {
3004 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3005 }
3006
Amit Shekhar6f461b12014-08-01 14:52:58 -07003007 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05303008 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003009
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3011 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003012
Sharad Sangleb27354b2015-06-18 15:58:55 +05303013 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003014 //this flag is set from framework only if its for PCM formats
3015 //no need to check for PCM format again
3016 out->non_blocking = 0;
3017 out->use_small_bufs = true;
3018 ALOGI("Keep write blocking for small buff: non_blockling %d",
3019 out->non_blocking);
3020 }
3021
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003022 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05303023 out->send_next_track_params = false;
3024 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003025 out->offload_state = OFFLOAD_STATE_IDLE;
3026 out->playback_started = 0;
3027
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003028 audio_extn_dts_create_state_notifier_node(out->usecase);
3029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 create_offload_callback_thread(out);
3031 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3032 __func__, config->offload_info.version,
3033 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003034 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003035 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003036 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3037 ret = voice_check_and_set_incall_music_usecase(adev, out);
3038 if (ret != 0) {
3039 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3040 __func__, ret);
3041 goto error_open;
3042 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003043 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3044 if (config->sample_rate == 0)
3045 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3046 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3047 config->sample_rate != 8000) {
3048 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3049 ret = -EINVAL;
3050 goto error_open;
3051 }
3052 out->sample_rate = config->sample_rate;
3053 out->config.rate = config->sample_rate;
3054 if (config->format == AUDIO_FORMAT_DEFAULT)
3055 config->format = AUDIO_FORMAT_PCM_16_BIT;
3056 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3057 config->format = AUDIO_FORMAT_PCM_16_BIT;
3058 ret = -EINVAL;
3059 goto error_open;
3060 }
3061 out->format = config->format;
3062 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3063 out->config = pcm_config_afe_proxy_playback;
3064 adev->voice_tx_output = out;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003065 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3066 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3067 out->config = pcm_config_low_latency;
3068 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003069 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003070 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3072 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003074 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3075 format = AUDIO_FORMAT_PCM_16_BIT;
3076 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3077 out->config = pcm_config_deep_buffer;
3078 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003079 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003080 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003081 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003082 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003083 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003084 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 }
3086
Amit Shekhar1d896042014-10-03 13:16:09 -07003087 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3088 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003089 /* TODO remove this hardcoding and check why width is zero*/
3090 if (out->bit_width == 0)
3091 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003092 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3093 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003094 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303095 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003096 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3097 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3098 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003099 if(adev->primary_output == NULL)
3100 adev->primary_output = out;
3101 else {
3102 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003103 ret = -EEXIST;
3104 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003105 }
3106 }
3107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 /* Check if this usecase is already existing */
3109 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003110 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3111 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003114 ret = -EEXIST;
3115 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 }
3117 pthread_mutex_unlock(&adev->lock);
3118
3119 out->stream.common.get_sample_rate = out_get_sample_rate;
3120 out->stream.common.set_sample_rate = out_set_sample_rate;
3121 out->stream.common.get_buffer_size = out_get_buffer_size;
3122 out->stream.common.get_channels = out_get_channels;
3123 out->stream.common.get_format = out_get_format;
3124 out->stream.common.set_format = out_set_format;
3125 out->stream.common.standby = out_standby;
3126 out->stream.common.dump = out_dump;
3127 out->stream.common.set_parameters = out_set_parameters;
3128 out->stream.common.get_parameters = out_get_parameters;
3129 out->stream.common.add_audio_effect = out_add_audio_effect;
3130 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3131 out->stream.get_latency = out_get_latency;
3132 out->stream.set_volume = out_set_volume;
3133 out->stream.write = out_write;
3134 out->stream.get_render_position = out_get_render_position;
3135 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003136 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003139 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003140 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
3142 config->format = out->stream.common.get_format(&out->stream.common);
3143 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3144 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3145
3146 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303147 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3148 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003149
3150 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3151 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3152 popcount(out->channel_mask), out->playback_started);
3153
Eric Laurent994a6932013-07-17 11:51:42 -07003154 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003156
3157error_open:
3158 free(out);
3159 *stream_out = NULL;
3160 ALOGD("%s: exit: ret %d", __func__, ret);
3161 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162}
3163
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003164static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 struct audio_stream_out *stream)
3166{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 struct stream_out *out = (struct stream_out *)stream;
3168 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003169 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303171 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3172
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003173 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303174 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003175 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303176 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003177 if(ret != 0)
3178 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3179 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003181 out_standby(&stream->common);
3182
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003183 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003184 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003185 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003186 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 if (out->compr_config.codec != NULL)
3188 free(out->compr_config.codec);
3189 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003190
3191 if (adev->voice_tx_output == out)
3192 adev->voice_tx_output = NULL;
3193
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003194 pthread_cond_destroy(&out->cond);
3195 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003197 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198}
3199
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003200static void close_compress_sessions(struct audio_device *adev)
3201{
Mingming Yin7b762e72015-03-04 13:47:32 -08003202 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303203 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003204 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003205 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303206
3207 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003208 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303209 if (is_offload_usecase(usecase->id)) {
3210 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003211 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3212 out = usecase->stream.out;
3213 pthread_mutex_unlock(&adev->lock);
3214 out_standby(&out->stream.common);
3215 pthread_mutex_lock(&adev->lock);
3216 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303217 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003218 }
3219 pthread_mutex_unlock(&adev->lock);
3220}
3221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3223{
3224 struct audio_device *adev = (struct audio_device *)dev;
3225 struct str_parms *parms;
3226 char *str;
3227 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003228 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003229 int ret;
3230 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003232 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303235 if (!parms)
3236 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003237 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3238 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303239 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303240 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303241 struct listnode *node;
3242 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303243 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303244 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003245 //close compress sessions on OFFLINE status
3246 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303247 } else if (strstr(snd_card_status, "ONLINE")) {
3248 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303249 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303250 if (!platform_is_acdb_initialized(adev->platform)) {
3251 ret = platform_acdb_init(adev->platform);
3252 if(ret)
3253 ALOGE("acdb initialization is failed");
3254
3255 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303256 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303257 }
3258
3259 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003260 status = voice_set_parameters(adev, parms);
3261 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003262 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003264 status = platform_set_parameters(adev->platform, parms);
3265 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003266 goto done;
3267
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003268 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3269 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003270 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3272 adev->bluetooth_nrec = true;
3273 else
3274 adev->bluetooth_nrec = false;
3275 }
3276
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003277 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3278 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3280 adev->screen_off = false;
3281 else
3282 adev->screen_off = true;
3283 }
3284
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003285 ret = str_parms_get_int(parms, "rotation", &val);
3286 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003287 bool reverse_speakers = false;
3288 switch(val) {
3289 // FIXME: note that the code below assumes that the speakers are in the correct placement
3290 // relative to the user when the device is rotated 90deg from its default rotation. This
3291 // assumption is device-specific, not platform-specific like this code.
3292 case 270:
3293 reverse_speakers = true;
3294 break;
3295 case 0:
3296 case 90:
3297 case 180:
3298 break;
3299 default:
3300 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003301 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003302 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003303 if (status == 0) {
3304 if (adev->speaker_lr_swap != reverse_speakers) {
3305 adev->speaker_lr_swap = reverse_speakers;
3306 // only update the selected device if there is active pcm playback
3307 struct audio_usecase *usecase;
3308 struct listnode *node;
3309 list_for_each(node, &adev->usecase_list) {
3310 usecase = node_to_item(node, struct audio_usecase, list);
3311 if (usecase->type == PCM_PLAYBACK) {
3312 select_devices(adev, usecase->id);
3313 break;
3314 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003315 }
3316 }
3317 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003318 }
3319
Mingming Yin514a8bc2014-07-29 15:22:21 -07003320 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3321 if (ret >= 0) {
3322 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3323 adev->bt_wb_speech_enabled = true;
3324 else
3325 adev->bt_wb_speech_enabled = false;
3326 }
3327
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003328 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3329 if (ret >= 0) {
3330 val = atoi(value);
3331 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3332 ALOGV("cache new edid");
3333 platform_cache_edid(adev->platform);
3334 }
3335 }
3336
3337 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3338 if (ret >= 0) {
3339 val = atoi(value);
3340 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3341 ALOGV("invalidate cached edid");
3342 platform_invalidate_edid(adev->platform);
3343 }
3344 }
3345
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003346 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003347
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003348done:
3349 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003350 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303351error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003352 ALOGV("%s: exit with code(%d)", __func__, status);
3353 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354}
3355
3356static char* adev_get_parameters(const struct audio_hw_device *dev,
3357 const char *keys)
3358{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003359 struct audio_device *adev = (struct audio_device *)dev;
3360 struct str_parms *reply = str_parms_create();
3361 struct str_parms *query = str_parms_create_str(keys);
3362 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303363 char value[256] = {0};
3364 int ret = 0;
3365
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003366 if (!query || !reply) {
3367 ALOGE("adev_get_parameters: failed to create query or reply");
3368 return NULL;
3369 }
3370
Naresh Tannirud7205b62014-06-20 02:54:48 +05303371 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3372 sizeof(value));
3373 if (ret >=0) {
3374 int val = 1;
3375 pthread_mutex_lock(&adev->snd_card_status.lock);
3376 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3377 val = 0;
3378 pthread_mutex_unlock(&adev->snd_card_status.lock);
3379 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3380 goto exit;
3381 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003382
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003383 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003384 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003385 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003386 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303387 pthread_mutex_unlock(&adev->lock);
3388
Naresh Tannirud7205b62014-06-20 02:54:48 +05303389exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003390 str = str_parms_to_str(reply);
3391 str_parms_destroy(query);
3392 str_parms_destroy(reply);
3393
3394 ALOGV("%s: exit: returns - %s", __func__, str);
3395 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396}
3397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003398static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399{
3400 return 0;
3401}
3402
3403static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3404{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003405 int ret;
3406 struct audio_device *adev = (struct audio_device *)dev;
3407 pthread_mutex_lock(&adev->lock);
3408 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003409 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003410 pthread_mutex_unlock(&adev->lock);
3411 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412}
3413
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003414static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3415 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416{
3417 return -ENOSYS;
3418}
3419
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003420static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3421 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422{
3423 return -ENOSYS;
3424}
3425
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003426static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3427 bool muted __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_mute(struct audio_hw_device *dev __unused,
3433 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434{
3435 return -ENOSYS;
3436}
3437
3438static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3439{
3440 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 pthread_mutex_lock(&adev->lock);
3443 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003444 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003446 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3447 voice_is_in_call(adev)) {
3448 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303449 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003450 adev->current_call_output = NULL;
3451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 }
3453 pthread_mutex_unlock(&adev->lock);
3454 return 0;
3455}
3456
3457static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3458{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003459 int ret;
3460
3461 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003462 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003463 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3464 pthread_mutex_unlock(&adev->lock);
3465
3466 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467}
3468
3469static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3470{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003471 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 return 0;
3473}
3474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003475static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 const struct audio_config *config)
3477{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003478 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003480 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3481 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482}
3483
3484static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003485 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486 audio_devices_t devices,
3487 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003488 struct audio_stream_in **stream_in,
3489 audio_input_flags_t flags __unused,
3490 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003491 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492{
3493 struct audio_device *adev = (struct audio_device *)dev;
3494 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003495 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003496 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003497 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 *stream_in = NULL;
3500 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3501 return -EINVAL;
3502
3503 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003504
3505 if (!in) {
3506 ALOGE("failed to allocate input stream");
3507 return -ENOMEM;
3508 }
3509
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303510 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003511 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3512 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003514 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07003515 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 in->stream.common.get_sample_rate = in_get_sample_rate;
3518 in->stream.common.set_sample_rate = in_set_sample_rate;
3519 in->stream.common.get_buffer_size = in_get_buffer_size;
3520 in->stream.common.get_channels = in_get_channels;
3521 in->stream.common.get_format = in_get_format;
3522 in->stream.common.set_format = in_set_format;
3523 in->stream.common.standby = in_standby;
3524 in->stream.common.dump = in_dump;
3525 in->stream.common.set_parameters = in_set_parameters;
3526 in->stream.common.get_parameters = in_get_parameters;
3527 in->stream.common.add_audio_effect = in_add_audio_effect;
3528 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3529 in->stream.set_gain = in_set_gain;
3530 in->stream.read = in_read;
3531 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3532
3533 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003534 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536 in->standby = 1;
3537 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003538 in->capture_handle = handle;
Naresh Tanniru4a080142015-06-15 10:35:19 -07003539 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540
3541 /* Update config params with the requested sample rate and channels */
3542 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003543 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3544 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3545 is_low_latency = true;
3546#if LOW_LATENCY_CAPTURE_USE_CASE
3547 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3548#endif
3549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003552 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003554 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303555 if (adev->mode != AUDIO_MODE_IN_CALL) {
3556 ret = -EINVAL;
3557 goto err_open;
3558 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003559 if (config->sample_rate == 0)
3560 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3561 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3562 config->sample_rate != 8000) {
3563 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3564 ret = -EINVAL;
3565 goto err_open;
3566 }
3567 if (config->format == AUDIO_FORMAT_DEFAULT)
3568 config->format = AUDIO_FORMAT_PCM_16_BIT;
3569 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3570 config->format = AUDIO_FORMAT_PCM_16_BIT;
3571 ret = -EINVAL;
3572 goto err_open;
3573 }
3574
3575 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3576 in->config = pcm_config_afe_proxy_record;
3577 in->config.channels = channel_count;
3578 in->config.rate = config->sample_rate;
3579 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003580 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003581 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003582 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3583 ret = -EINVAL;
3584 goto err_open;
3585 }
3586 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003587 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003588 }
Mingming Yine62d7842013-10-25 16:26:03 -07003589 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003590 audio_extn_compr_cap_format_supported(config->format) &&
3591 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003592 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003593 } else {
3594 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003595 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003596 buffer_size = get_input_buffer_size(config->sample_rate,
3597 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003598 channel_count,
3599 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003600 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003601 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3602 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3603 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3604 (in->config.rate == 8000 || in->config.rate == 16000) &&
3605 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3606 voice_extn_compress_voip_open_input_stream(in);
3607 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003610 /* This stream could be for sound trigger lab,
3611 get sound trigger pcm if present */
3612 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303613 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003616 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003617 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618
3619err_open:
3620 free(in);
3621 *stream_in = NULL;
3622 return ret;
3623}
3624
3625static void adev_close_input_stream(struct audio_hw_device *dev,
3626 struct audio_stream_in *stream)
3627{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003628 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003629 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003630 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303631
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303632 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003633
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303634 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003635 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303636
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003637 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303638 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003639 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303640 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003641 if (ret != 0)
3642 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3643 __func__, ret);
3644 } else
3645 in_standby(&stream->common);
3646
Mingming Yin7b762e72015-03-04 13:47:32 -08003647 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003648 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003649 audio_extn_ssr_deinit();
3650 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651
Mingming Yine62d7842013-10-25 16:26:03 -07003652 if(audio_extn_compr_cap_enabled() &&
3653 audio_extn_compr_cap_format_supported(in->config.format))
3654 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003655
3656 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 return;
3658}
3659
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003660static int adev_dump(const audio_hw_device_t *device __unused,
3661 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662{
3663 return 0;
3664}
3665
3666static int adev_close(hw_device_t *device)
3667{
3668 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003669
3670 if (!adev)
3671 return 0;
3672
3673 pthread_mutex_lock(&adev_init_lock);
3674
3675 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003676 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003677 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003678 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003679 audio_route_free(adev->audio_route);
3680 free(adev->snd_dev_ref_cnt);
3681 platform_deinit(adev->platform);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003682 if (adev->adm_deinit)
3683 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003684 free(device);
3685 adev = NULL;
3686 }
3687 pthread_mutex_unlock(&adev_init_lock);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 return 0;
3690}
3691
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003692/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3693 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3694 * just that it _might_ work.
3695 */
3696static int period_size_is_plausible_for_low_latency(int period_size)
3697{
3698 switch (period_size) {
3699 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003700 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003701 case 240:
3702 case 320:
3703 case 480:
3704 return 1;
3705 default:
3706 return 0;
3707 }
3708}
3709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710static int adev_open(const hw_module_t *module, const char *name,
3711 hw_device_t **device)
3712{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003713 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003715 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3717
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003718 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003719 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003720 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003721 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003722 ALOGD("%s: returning existing instance of adev", __func__);
3723 ALOGD("%s: exit", __func__);
3724 pthread_mutex_unlock(&adev_init_lock);
3725 return 0;
3726 }
3727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 adev = calloc(1, sizeof(struct audio_device));
3729
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003730 if (!adev) {
3731 pthread_mutex_unlock(&adev_init_lock);
3732 return -ENOMEM;
3733 }
3734
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003735 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3738 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3739 adev->device.common.module = (struct hw_module_t *)module;
3740 adev->device.common.close = adev_close;
3741
3742 adev->device.init_check = adev_init_check;
3743 adev->device.set_voice_volume = adev_set_voice_volume;
3744 adev->device.set_master_volume = adev_set_master_volume;
3745 adev->device.get_master_volume = adev_get_master_volume;
3746 adev->device.set_master_mute = adev_set_master_mute;
3747 adev->device.get_master_mute = adev_get_master_mute;
3748 adev->device.set_mode = adev_set_mode;
3749 adev->device.set_mic_mute = adev_set_mic_mute;
3750 adev->device.get_mic_mute = adev_get_mic_mute;
3751 adev->device.set_parameters = adev_set_parameters;
3752 adev->device.get_parameters = adev_get_parameters;
3753 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3754 adev->device.open_output_stream = adev_open_output_stream;
3755 adev->device.close_output_stream = adev_close_output_stream;
3756 adev->device.open_input_stream = adev_open_input_stream;
3757 adev->device.close_input_stream = adev_close_input_stream;
3758 adev->device.dump = adev_dump;
3759
3760 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003762 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003763 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003766 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003767 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003768 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003769 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003770 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003771 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003772 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303773 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303774
3775 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3776 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003778 adev->platform = platform_init(adev);
3779 if (!adev->platform) {
3780 free(adev->snd_dev_ref_cnt);
3781 free(adev);
3782 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3783 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003784 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003785 return -EINVAL;
3786 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003787
Naresh Tanniru4c630392014-05-12 01:05:52 +05303788 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3789
Eric Laurentc4aef752013-09-12 17:45:53 -07003790 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3791 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3792 if (adev->visualizer_lib == NULL) {
3793 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3794 } else {
3795 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3796 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003797 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003798 "visualizer_hal_start_output");
3799 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003800 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003801 "visualizer_hal_stop_output");
3802 }
3803 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003804 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003805 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003806
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003807 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3808 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3809 if (adev->offload_effects_lib == NULL) {
3810 ALOGE("%s: DLOPEN failed for %s", __func__,
3811 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3812 } else {
3813 ALOGV("%s: DLOPEN successful for %s", __func__,
3814 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3815 adev->offload_effects_start_output =
3816 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3817 "offload_effects_bundle_hal_start_output");
3818 adev->offload_effects_stop_output =
3819 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3820 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003821 adev->offload_effects_set_hpx_state =
3822 (int (*)(bool))dlsym(adev->offload_effects_lib,
3823 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303824 adev->offload_effects_get_parameters =
3825 (void (*)(struct str_parms *, struct str_parms *))
3826 dlsym(adev->offload_effects_lib,
3827 "offload_effects_bundle_get_parameters");
3828 adev->offload_effects_set_parameters =
3829 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3830 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003831 }
3832 }
3833
Naresh Tanniru4a080142015-06-15 10:35:19 -07003834 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3835 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3836 if (adev->adm_lib == NULL) {
3837 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3838 } else {
3839 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3840 adev->adm_init = (adm_init_t)
3841 dlsym(adev->adm_lib, "adm_init");
3842 adev->adm_deinit = (adm_deinit_t)
3843 dlsym(adev->adm_lib, "adm_deinit");
3844 adev->adm_register_input_stream = (adm_register_input_stream_t)
3845 dlsym(adev->adm_lib, "adm_register_input_stream");
3846 adev->adm_register_output_stream = (adm_register_output_stream_t)
3847 dlsym(adev->adm_lib, "adm_register_output_stream");
3848 adev->adm_deregister_stream = (adm_deregister_stream_t)
3849 dlsym(adev->adm_lib, "adm_deregister_stream");
3850 adev->adm_request_focus = (adm_request_focus_t)
3851 dlsym(adev->adm_lib, "adm_request_focus");
3852 adev->adm_abandon_focus = (adm_abandon_focus_t)
3853 dlsym(adev->adm_lib, "adm_abandon_focus");
3854 }
3855 }
3856
Mingming Yin514a8bc2014-07-29 15:22:21 -07003857 adev->bt_wb_speech_enabled = false;
3858
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003859 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 *device = &adev->device.common;
3861
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003862 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3863 &adev->streams_output_cfg_list);
3864
Kiran Kandi910e1862013-10-29 13:29:42 -07003865 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003866
3867 char value[PROPERTY_VALUE_MAX];
3868 int trial;
3869 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3870 trial = atoi(value);
3871 if (period_size_is_plausible_for_low_latency(trial)) {
3872 pcm_config_low_latency.period_size = trial;
3873 pcm_config_low_latency.start_threshold = trial / 4;
3874 pcm_config_low_latency.avail_min = trial / 4;
3875 configured_low_latency_capture_period_size = trial;
3876 }
3877 }
3878 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3879 trial = atoi(value);
3880 if (period_size_is_plausible_for_low_latency(trial)) {
3881 configured_low_latency_capture_period_size = trial;
3882 }
3883 }
3884
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003885 pthread_mutex_unlock(&adev_init_lock);
3886
Naresh Tanniru4a080142015-06-15 10:35:19 -07003887 if (adev->adm_init)
3888 adev->adm_data = adev->adm_init();
3889
Eric Laurent994a6932013-07-17 11:51:42 -07003890 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 return 0;
3892}
3893
3894static struct hw_module_methods_t hal_module_methods = {
3895 .open = adev_open,
3896};
3897
3898struct audio_module HAL_MODULE_INFO_SYM = {
3899 .common = {
3900 .tag = HARDWARE_MODULE_TAG,
3901 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3902 .hal_api_version = HARDWARE_HAL_API_VERSION,
3903 .id = AUDIO_HARDWARE_MODULE_ID,
3904 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003905 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 .methods = &hal_module_methods,
3907 },
3908};