blob: 9b6ddd6bf8fbb200fff2397075fcfc4c07be15d5 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700171#ifdef MULTIPLE_OFFLOAD_ENABLED
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
180#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700181 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700184 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700186 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700187 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800188 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800189 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700191
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700192 [USECASE_VOICE2_CALL] = "voice2-call",
193 [USECASE_VOLTE_CALL] = "volte-call",
194 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800195 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800196 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
197 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800198 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700199 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
200 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800202 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
203 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
204 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
205
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700206 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
207 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700208 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
209 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700210
211 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
212 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700213};
214
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215static const audio_usecase_t offload_usecases[] = {
216 USECASE_AUDIO_PLAYBACK_OFFLOAD,
217#ifdef MULTIPLE_OFFLOAD_ENABLED
218 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
225 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
226#endif
vivek mehta0ea887a2015-08-26 14:01:20 -0700227 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700228};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229
230#define STRING_TO_ENUM(string) { #string, string }
231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800232struct string_to_enum {
233 const char *name;
234 uint32_t value;
235};
236
237static const struct string_to_enum out_channels_name_to_enum_table[] = {
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
245};
246
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700247static const struct string_to_enum out_formats_name_to_enum_table[] = {
248 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
250 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
251};
252
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700253static struct audio_device *adev = NULL;
254static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700255static unsigned int audio_device_ref_count;
256
Haynes Mathew George5191a852013-09-11 14:19:36 -0700257static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800258
vivek mehtaa76401a2015-04-24 14:12:15 -0700259__attribute__ ((visibility ("default")))
260bool audio_hw_send_gain_dep_calibration(int level) {
261 bool ret_val = false;
262 ALOGV("%s: called ... ", __func__);
263
264 pthread_mutex_lock(&adev_init_lock);
265
266 if (adev != NULL && adev->platform != NULL) {
267 pthread_mutex_lock(&adev->lock);
268 ret_val = platform_send_gain_dep_cal(adev->platform, level);
269 pthread_mutex_unlock(&adev->lock);
270 } else {
271 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
272 }
273
274 pthread_mutex_unlock(&adev_init_lock);
275
276 return ret_val;
277}
278
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800279static int check_and_set_gapless_mode(struct audio_device *adev) {
280
281
282 char value[PROPERTY_VALUE_MAX] = {0};
283 bool gapless_enabled = false;
284 const char *mixer_ctl_name = "Compress Gapless Playback";
285 struct mixer_ctl *ctl;
286
287 ALOGV("%s:", __func__);
288 property_get("audio.offload.gapless.enabled", value, NULL);
289 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
290
291 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
292 if (!ctl) {
293 ALOGE("%s: Could not get ctl for mixer cmd - %s",
294 __func__, mixer_ctl_name);
295 return -EINVAL;
296 }
297
298 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
299 ALOGE("%s: Could not set gapless mode %d",
300 __func__, gapless_enabled);
301 return -EINVAL;
302 }
303 return 0;
304}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700305
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306static bool is_supported_format(audio_format_t format)
307{
Eric Laurent86e17132013-09-12 17:49:30 -0700308 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 format == AUDIO_FORMAT_AAC_LC ||
310 format == AUDIO_FORMAT_AAC_HE_V1 ||
311 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530312 format == AUDIO_FORMAT_AAC_ADTS_LC ||
313 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
314 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800315 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700316 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700317 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800318 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530319 format == AUDIO_FORMAT_ALAC ||
320 format == AUDIO_FORMAT_APE ||
321 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800322 format == AUDIO_FORMAT_WMA ||
323 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800324 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700325
326 return false;
327}
328
329static int get_snd_codec_id(audio_format_t format)
330{
331 int id = 0;
332
Ashish Jainf9b78162014-08-25 20:36:25 +0530333 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700334 case AUDIO_FORMAT_MP3:
335 id = SND_AUDIOCODEC_MP3;
336 break;
337 case AUDIO_FORMAT_AAC:
338 id = SND_AUDIOCODEC_AAC;
339 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530340 case AUDIO_FORMAT_AAC_ADTS:
341 id = SND_AUDIOCODEC_AAC;
342 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530343 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700344 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800345 id = SND_AUDIOCODEC_PCM;
346 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700347 case AUDIO_FORMAT_FLAC:
348 id = SND_AUDIOCODEC_FLAC;
349 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530350 case AUDIO_FORMAT_ALAC:
351 id = SND_AUDIOCODEC_ALAC;
352 break;
353 case AUDIO_FORMAT_APE:
354 id = SND_AUDIOCODEC_APE;
355 break;
356 case AUDIO_FORMAT_VORBIS:
357 id = SND_AUDIOCODEC_VORBIS;
358 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800359 case AUDIO_FORMAT_WMA:
360 id = SND_AUDIOCODEC_WMA;
361 break;
362 case AUDIO_FORMAT_WMA_PRO:
363 id = SND_AUDIOCODEC_WMA_PRO;
364 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700365 default:
Mingming Yin90310102013-11-13 16:57:00 -0800366 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700367 }
368
369 return id;
370}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800371
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530372int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530373{
374 int snd_scard_state;
375
376 if (!adev)
377 return SND_CARD_STATE_OFFLINE;
378
379 pthread_mutex_lock(&adev->snd_card_status.lock);
380 snd_scard_state = adev->snd_card_status.state;
381 pthread_mutex_unlock(&adev->snd_card_status.lock);
382
383 return snd_scard_state;
384}
385
386static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
387{
388 if (!adev)
389 return -ENOSYS;
390
391 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700392 if (adev->snd_card_status.state != snd_scard_state) {
393 adev->snd_card_status.state = snd_scard_state;
394 platform_snd_card_update(adev->platform, snd_scard_state);
395 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530396 pthread_mutex_unlock(&adev->snd_card_status.lock);
397
398 return 0;
399}
400
Avinash Vaish71a8b972014-07-24 15:36:33 +0530401static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
402 struct audio_usecase *uc_info)
403{
404 struct listnode *node;
405 struct audio_usecase *usecase;
406
407 if (uc_info == NULL)
408 return -EINVAL;
409
410 /* Re-route all voice usecases on the shared backend other than the
411 specified usecase to new snd devices */
412 list_for_each(node, &adev->usecase_list) {
413 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800414 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530415 enable_audio_route(adev, usecase);
416 }
417 return 0;
418}
419
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700420int pcm_ioctl(struct pcm *pcm, int request, ...)
421{
422 va_list ap;
423 void * arg;
424 int pcm_fd = *(int*)pcm;
425
426 va_start(ap, request);
427 arg = va_arg(ap, void *);
428 va_end(ap);
429
430 return ioctl(pcm_fd, request, arg);
431}
432
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700433int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700434 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700436 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700437 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438
439 if (usecase == NULL)
440 return -EINVAL;
441
442 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
443
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800444 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800448
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800449#ifdef DS1_DOLBY_DAP_ENABLED
450 audio_extn_dolby_set_dmid(adev);
451 audio_extn_dolby_set_endpoint(adev);
452#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700453 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700454 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530455 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700456 audio_extn_utils_send_audio_calibration(adev, usecase);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700457 audio_extn_utils_send_app_type_cfg(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800458 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700459 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700460 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700461 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462 ALOGV("%s: exit", __func__);
463 return 0;
464}
465
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700466int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700467 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800468{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700470 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800471
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530472 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800473 return -EINVAL;
474
475 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700476 if (usecase->type == PCM_CAPTURE)
477 snd_device = usecase->in_snd_device;
478 else
479 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800480 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700481 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700482 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700483 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700484 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530485 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800486 ALOGV("%s: exit", __func__);
487 return 0;
488}
489
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700490int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700491 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800492{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700493 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
494
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800495 if (snd_device < SND_DEVICE_MIN ||
496 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800497 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800498 return -EINVAL;
499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700500
501 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700502
503 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
504 ALOGE("%s: Invalid sound device returned", __func__);
505 return -EINVAL;
506 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700507 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700508 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700509 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700510 return 0;
511 }
512
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700513 if (audio_extn_spkr_prot_is_enabled())
514 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700515 /* start usb playback thread */
516 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
517 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
518 audio_extn_usb_start_playback(adev);
519
520 /* start usb capture thread */
521 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
522 audio_extn_usb_start_capture(adev);
523
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800524 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700525 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
526 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
527 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
528 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700529 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
530 adev->snd_dev_ref_cnt[snd_device]--;
531 return -EINVAL;
532 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200533 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800534 if (audio_extn_spkr_prot_start_processing(snd_device)) {
535 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200536 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800537 return -EINVAL;
538 }
539 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700540 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700541 /* due to the possibility of calibration overwrite between listen
542 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543 audio_extn_sound_trigger_update_device_status(snd_device,
544 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530545 audio_extn_listen_update_device_status(snd_device,
546 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700547 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700548 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700549 audio_extn_sound_trigger_update_device_status(snd_device,
550 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530551 audio_extn_listen_update_device_status(snd_device,
552 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700553 return -EINVAL;
554 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300555 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700556 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 return 0;
559}
560
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700561int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700562 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700564 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800566 if (snd_device < SND_DEVICE_MIN ||
567 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800568 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 return -EINVAL;
570 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
572 ALOGE("%s: device ref cnt is already 0", __func__);
573 return -EINVAL;
574 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700575
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700577
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
579 ALOGE("%s: Invalid sound device returned", __func__);
580 return -EINVAL;
581 }
582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700584 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800585 /* exit usb play back thread */
586 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
587 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
588 audio_extn_usb_stop_playback();
589
590 /* exit usb capture thread */
591 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700592 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800593
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800594 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700595 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
596 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
597 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200604 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700605 audio_extn_sound_trigger_update_device_status(snd_device,
606 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530607 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800608 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800611 return 0;
612}
613
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614static void check_usecases_codec_backend(struct audio_device *adev,
615 struct audio_usecase *uc_info,
616 snd_device_t snd_device)
617{
618 struct listnode *node;
619 struct audio_usecase *usecase;
620 bool switch_device[AUDIO_USECASE_MAX];
621 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800622 int backend_idx = DEFAULT_CODEC_BACKEND;
623 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700624
625 /*
626 * This function is to make sure that all the usecases that are active on
627 * the hardware codec backend are always routed to any one device that is
628 * handled by the hardware codec.
629 * For example, if low-latency and deep-buffer usecases are currently active
630 * on speaker and out_set_parameters(headset) is received on low-latency
631 * output, then we have to make sure deep-buffer is also switched to headset,
632 * because of the limitation that both the devices cannot be enabled
633 * at the same time as they share the same backend.
634 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700635 /*
636 * This call is to check if we need to force routing for a particular stream
637 * If there is a backend configuration change for the device when a
638 * new stream starts, then ADM needs to be closed and re-opened with the new
639 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800640 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700641 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800642 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
643 snd_device);
644 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800646 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800647 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 for (i = 0; i < AUDIO_USECASE_MAX; i++)
649 switch_device[i] = false;
650
651 list_for_each(node, &adev->usecase_list) {
652 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653
654 if (usecase == uc_info)
655 continue;
656 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
657 ALOGV("%s: backend_idx: %d,"
658 "usecase_backend_idx: %d, curr device: %s, usecase device:"
659 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530660 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800661
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800662 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700663 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800664 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
665 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530666 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700668 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700669 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 switch_device[usecase->id] = true;
671 num_uc_to_switch++;
672 }
673 }
674
675 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700676 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530678 /* Make sure the previous devices to be disabled first and then enable the
679 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 list_for_each(node, &adev->usecase_list) {
681 usecase = node_to_item(node, struct audio_usecase, list);
682 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700683 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 }
685 }
686
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700687 list_for_each(node, &adev->usecase_list) {
688 usecase = node_to_item(node, struct audio_usecase, list);
689 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700690 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700691 }
692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 /* Re-route all the usecases on the shared backend other than the
695 specified usecase to new snd devices */
696 list_for_each(node, &adev->usecase_list) {
697 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530698 /* Update the out_snd_device only for the usecases that are enabled here */
699 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
700 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530701 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 }
703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 }
705}
706
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700707static void check_and_route_capture_usecases(struct audio_device *adev,
708 struct audio_usecase *uc_info,
709 snd_device_t snd_device)
710{
711 struct listnode *node;
712 struct audio_usecase *usecase;
713 bool switch_device[AUDIO_USECASE_MAX];
714 int i, num_uc_to_switch = 0;
715
716 /*
717 * This function is to make sure that all the active capture usecases
718 * are always routed to the same input sound device.
719 * For example, if audio-record and voice-call usecases are currently
720 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
721 * is received for voice call then we have to make sure that audio-record
722 * usecase is also switched to earpiece i.e. voice-dmic-ef,
723 * because of the limitation that two devices cannot be enabled
724 * at the same time if they share the same backend.
725 */
726 for (i = 0; i < AUDIO_USECASE_MAX; i++)
727 switch_device[i] = false;
728
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800731 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700733 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700734 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
735 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700736 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
738 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700739 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700740 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700741 switch_device[usecase->id] = true;
742 num_uc_to_switch++;
743 }
744 }
745
746 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700747 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530749 /* Make sure the previous devices to be disabled first and then enable the
750 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700751 list_for_each(node, &adev->usecase_list) {
752 usecase = node_to_item(node, struct audio_usecase, list);
753 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700754 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800755 }
756 }
757
758 list_for_each(node, &adev->usecase_list) {
759 usecase = node_to_item(node, struct audio_usecase, list);
760 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700761 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 }
763 }
764
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700765 /* Re-route all the usecases on the shared backend other than the
766 specified usecase to new snd devices */
767 list_for_each(node, &adev->usecase_list) {
768 usecase = node_to_item(node, struct audio_usecase, list);
769 /* Update the in_snd_device only before enabling the audio route */
770 if (switch_device[usecase->id] ) {
771 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800772 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530773 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 }
775 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 }
777}
778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700780static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700782 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700783 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784
785 switch (channels) {
786 /*
787 * Do not handle stereo output in Multi-channel cases
788 * Stereo case is handled in normal playback path
789 */
790 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700791 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 break;
798 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700799 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
801 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
804 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
805 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806 break;
807 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700808 ALOGE("HDMI does not support multi channel playback");
809 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810 break;
811 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700812 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800813}
814
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800815audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
816 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700817{
818 struct audio_usecase *usecase;
819 struct listnode *node;
820
821 list_for_each(node, &adev->usecase_list) {
822 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800823 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700824 ALOGV("%s: usecase id %d", __func__, usecase->id);
825 return usecase->id;
826 }
827 }
828 return USECASE_INVALID;
829}
830
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700831struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700832 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833{
834 struct audio_usecase *usecase;
835 struct listnode *node;
836
837 list_for_each(node, &adev->usecase_list) {
838 usecase = node_to_item(node, struct audio_usecase, list);
839 if (usecase->id == uc_id)
840 return usecase;
841 }
842 return NULL;
843}
844
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700845int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800846{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800847 snd_device_t out_snd_device = SND_DEVICE_NONE;
848 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 struct audio_usecase *usecase = NULL;
850 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800851 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800852 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800853 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800854 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 usecase = get_usecase_from_list(adev, uc_id);
858 if (usecase == NULL) {
859 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
860 return -EINVAL;
861 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800863 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800864 (usecase->type == VOIP_CALL) ||
865 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800867 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 usecase->devices = usecase->stream.out->devices;
870 } else {
871 /*
872 * If the voice call is active, use the sound devices of voice call usecase
873 * so that it would not result any device switch. All the usecases will
874 * be switched to new device when select_devices() is called for voice call
875 * usecase. This is to avoid switching devices for voice call when
876 * check_usecases_codec_backend() is called below.
877 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700878 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700879 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800880 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700881 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
882 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 in_snd_device = vc_usecase->in_snd_device;
884 out_snd_device = vc_usecase->out_snd_device;
885 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800886 } else if (voice_extn_compress_voip_is_active(adev)) {
887 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700888 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530889 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700890 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800891 in_snd_device = voip_usecase->in_snd_device;
892 out_snd_device = voip_usecase->out_snd_device;
893 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800894 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800895 hfp_ucid = audio_extn_hfp_get_usecase();
896 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700897 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800898 in_snd_device = hfp_usecase->in_snd_device;
899 out_snd_device = hfp_usecase->out_snd_device;
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902 if (usecase->type == PCM_PLAYBACK) {
903 usecase->devices = usecase->stream.out->devices;
904 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700905 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700906 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800907 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700908 if (usecase->stream.out == adev->primary_output &&
909 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800910 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700911 select_devices(adev, adev->active_input->usecase);
912 }
913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914 } else if (usecase->type == PCM_CAPTURE) {
915 usecase->devices = usecase->stream.in->device;
916 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700917 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700918 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530919 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
920 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
921 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
922 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700923 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700924 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700925 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
926 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700927 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700928 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700929 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700930 }
931 }
932
933 if (out_snd_device == usecase->out_snd_device &&
934 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935 return 0;
936 }
937
sangwoobc677242013-08-08 16:53:43 +0900938 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700939 out_snd_device, platform_get_snd_device_name(out_snd_device),
940 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800942 /*
943 * Limitation: While in call, to do a device switch we need to disable
944 * and enable both RX and TX devices though one of them is same as current
945 * device.
946 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700947 if ((usecase->type == VOICE_CALL) &&
948 (usecase->in_snd_device != SND_DEVICE_NONE) &&
949 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700950 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700951 }
952
953 if (((usecase->type == VOICE_CALL) ||
954 (usecase->type == VOIP_CALL)) &&
955 (usecase->out_snd_device != SND_DEVICE_NONE)) {
956 /* Disable sidetone only if voice/voip call already exists */
957 if (voice_is_call_state_active(adev) ||
958 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700959 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800960 }
961
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 /* Disable current sound devices */
963 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 disable_audio_route(adev, usecase);
965 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 }
967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 disable_audio_route(adev, usecase);
970 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971 }
972
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800973 /* Applicable only on the targets that has external modem.
974 * New device information should be sent to modem before enabling
975 * the devices to reduce in-call device switch time.
976 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700977 if ((usecase->type == VOICE_CALL) &&
978 (usecase->in_snd_device != SND_DEVICE_NONE) &&
979 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800980 status = platform_switch_voice_call_enable_device_config(adev->platform,
981 out_snd_device,
982 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700983 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 /* Enable new sound devices */
986 if (out_snd_device != SND_DEVICE_NONE) {
987 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
988 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700989 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 }
991
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992 if (in_snd_device != SND_DEVICE_NONE) {
993 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700994 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700995 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700996
Avinash Vaish71a8b972014-07-24 15:36:33 +0530997 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700998 status = platform_switch_voice_call_device_post(adev->platform,
999 out_snd_device,
1000 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301001 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001002 /* Enable sidetone only if voice/voip call already exists */
1003 if (voice_is_call_state_active(adev) ||
1004 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001005 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301006 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001007
sangwoo170731f2013-06-08 15:36:36 +09001008 usecase->in_snd_device = in_snd_device;
1009 usecase->out_snd_device = out_snd_device;
1010
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301011 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001012 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001014 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301015 usecase->stream.out->flags,
1016 usecase->stream.out->format,
1017 usecase->stream.out->sample_rate,
1018 usecase->stream.out->bit_width,
1019 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001020 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301021 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001022
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001023 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001024
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001025 /* Applicable only on the targets that has external modem.
1026 * Enable device command should be sent to modem only after
1027 * enabling voice call mixer controls
1028 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001029 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001030 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1031 out_snd_device,
1032 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301033 ALOGD("%s: done",__func__);
1034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035 return status;
1036}
1037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038static int stop_input_stream(struct stream_in *in)
1039{
1040 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 struct audio_usecase *uc_info;
1042 struct audio_device *adev = in->dev;
1043
Eric Laurentc8400632013-02-14 19:04:54 -08001044 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045
Eric Laurent994a6932013-07-17 11:51:42 -07001046 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 uc_info = get_usecase_from_list(adev, in->usecase);
1049 if (uc_info == NULL) {
1050 ALOGE("%s: Could not find the usecase (%d) in the list",
1051 __func__, in->usecase);
1052 return -EINVAL;
1053 }
1054
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001055 /* Close in-call recording streams */
1056 voice_check_and_stop_incall_rec_usecase(adev, in);
1057
Eric Laurent150dbfe2013-02-27 14:31:02 -08001058 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060
1061 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001062 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001064 list_remove(&uc_info->list);
1065 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066
Eric Laurent994a6932013-07-17 11:51:42 -07001067 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 return ret;
1069}
1070
1071int start_input_stream(struct stream_in *in)
1072{
1073 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001074 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 struct audio_usecase *uc_info;
1076 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301077 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078
Mingming Yin2664a5b2015-09-03 10:53:11 -07001079 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1080 if (get_usecase_from_list(adev, usecase) == NULL)
1081 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301082 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1083 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001084
Naresh Tanniru80659832014-06-04 18:17:56 +05301085
1086 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301088 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089 goto error_config;
1090 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301091
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001092 /* Check if source matches incall recording usecase criteria */
1093 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1094 if (ret)
1095 goto error_config;
1096 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001097 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1098
1099 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1100 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1101 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1102 goto error_config;
1103 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001104
Eric Laurentb23d5282013-05-14 15:27:20 -07001105 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106 if (in->pcm_device_id < 0) {
1107 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1108 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001109 ret = -EINVAL;
1110 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112
1113 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001115
1116 if (!uc_info) {
1117 ret = -ENOMEM;
1118 goto error_config;
1119 }
1120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 uc_info->id = in->usecase;
1122 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001123 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 uc_info->devices = in->device;
1125 uc_info->in_snd_device = SND_DEVICE_NONE;
1126 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001128 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301129 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131
Eric Laurentc8400632013-02-14 19:04:54 -08001132 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001133 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1134
1135 unsigned int flags = PCM_IN;
1136 unsigned int pcm_open_retry_count = 0;
1137
1138 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1139 flags |= PCM_MMAP | PCM_NOIRQ;
1140 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1141 }
1142
1143 while (1) {
1144 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1145 flags, &in->config);
1146 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1147 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1148 if (in->pcm != NULL) {
1149 pcm_close(in->pcm);
1150 in->pcm = NULL;
1151 }
1152 if (pcm_open_retry_count-- == 0) {
1153 ret = -EIO;
1154 goto error_open;
1155 }
1156 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1157 continue;
1158 }
1159 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001160 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001161
1162 ALOGV("%s: pcm_prepare", __func__);
1163 ret = pcm_prepare(in->pcm);
1164 if (ret < 0) {
1165 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1166 pcm_close(in->pcm);
1167 in->pcm = NULL;
1168 goto error_open;
1169 }
1170
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301171 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301172
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001173 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001174
Eric Laurentc8400632013-02-14 19:04:54 -08001175 return ret;
1176
1177error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301179 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001180
1181error_config:
1182 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301183 /*
1184 * sleep 50ms to allow sufficient time for kernel
1185 * drivers to recover incases like SSR.
1186 */
1187 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001189
1190 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191}
1192
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001193void lock_input_stream(struct stream_in *in)
1194{
1195 pthread_mutex_lock(&in->pre_lock);
1196 pthread_mutex_lock(&in->lock);
1197 pthread_mutex_unlock(&in->pre_lock);
1198}
1199
1200void lock_output_stream(struct stream_out *out)
1201{
1202 pthread_mutex_lock(&out->pre_lock);
1203 pthread_mutex_lock(&out->lock);
1204 pthread_mutex_unlock(&out->pre_lock);
1205}
1206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001207/* must be called with out->lock locked */
1208static int send_offload_cmd_l(struct stream_out* out, int command)
1209{
1210 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1211
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001212 if (!cmd) {
1213 ALOGE("failed to allocate mem for command 0x%x", command);
1214 return -ENOMEM;
1215 }
1216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 ALOGVV("%s %d", __func__, command);
1218
1219 cmd->cmd = command;
1220 list_add_tail(&out->offload_cmd_list, &cmd->node);
1221 pthread_cond_signal(&out->offload_cond);
1222 return 0;
1223}
1224
1225/* must be called iwth out->lock locked */
1226static void stop_compressed_output_l(struct stream_out *out)
1227{
1228 out->offload_state = OFFLOAD_STATE_IDLE;
1229 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001230 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001231 if (out->compr != NULL) {
1232 compress_stop(out->compr);
1233 while (out->offload_thread_blocked) {
1234 pthread_cond_wait(&out->cond, &out->lock);
1235 }
1236 }
1237}
1238
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001239bool is_offload_usecase(audio_usecase_t uc_id)
1240{
1241 unsigned int i;
1242 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1243 if (uc_id == offload_usecases[i])
1244 return true;
1245 }
1246 return false;
1247}
1248
1249static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1250{
1251 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1252 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1253 char value[PROPERTY_VALUE_MAX] = {0};
1254
1255 property_get("audio.offload.multiple.enabled", value, NULL);
1256 if (!(atoi(value) || !strncmp("true", value, 4)))
1257 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1258
1259 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1260 for (i = 0; i < num_usecase; i++) {
1261 if (!(adev->offload_usecases_state & (0x1<<i))) {
1262 adev->offload_usecases_state |= 0x1 << i;
1263 ret = offload_usecases[i];
1264 break;
1265 }
1266 }
1267 ALOGV("%s: offload usecase is %d", __func__, ret);
1268 return ret;
1269}
1270
1271static void free_offload_usecase(struct audio_device *adev,
1272 audio_usecase_t uc_id)
1273{
1274 unsigned int i;
1275 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1276 if (offload_usecases[i] == uc_id) {
1277 adev->offload_usecases_state &= ~(0x1<<i);
1278 break;
1279 }
1280 }
1281 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1282}
1283
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001284static void *offload_thread_loop(void *context)
1285{
1286 struct stream_out *out = (struct stream_out *) context;
1287 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001288 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1291 set_sched_policy(0, SP_FOREGROUND);
1292 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1293
1294 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001295 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001296 for (;;) {
1297 struct offload_cmd *cmd = NULL;
1298 stream_callback_event_t event;
1299 bool send_callback = false;
1300
1301 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1302 __func__, list_empty(&out->offload_cmd_list),
1303 out->offload_state);
1304 if (list_empty(&out->offload_cmd_list)) {
1305 ALOGV("%s SLEEPING", __func__);
1306 pthread_cond_wait(&out->offload_cond, &out->lock);
1307 ALOGV("%s RUNNING", __func__);
1308 continue;
1309 }
1310
1311 item = list_head(&out->offload_cmd_list);
1312 cmd = node_to_item(item, struct offload_cmd, node);
1313 list_remove(item);
1314
1315 ALOGVV("%s STATE %d CMD %d out->compr %p",
1316 __func__, out->offload_state, cmd->cmd, out->compr);
1317
1318 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1319 free(cmd);
1320 break;
1321 }
1322
1323 if (out->compr == NULL) {
1324 ALOGE("%s: Compress handle is NULL", __func__);
1325 pthread_cond_signal(&out->cond);
1326 continue;
1327 }
1328 out->offload_thread_blocked = true;
1329 pthread_mutex_unlock(&out->lock);
1330 send_callback = false;
1331 switch(cmd->cmd) {
1332 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001333 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001334 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001335 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001336 send_callback = true;
1337 event = STREAM_CBK_EVENT_WRITE_READY;
1338 break;
1339 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001340 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301341 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001342 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301343 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001344 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301345 if (ret < 0)
1346 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301347 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301348 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001349 compress_drain(out->compr);
1350 else
1351 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301352 if (ret != -ENETRESET) {
1353 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301354 pthread_mutex_lock(&out->lock);
1355 out->send_new_metadata = 1;
1356 out->send_next_track_params = true;
1357 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301358 event = STREAM_CBK_EVENT_DRAIN_READY;
1359 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1360 } else
1361 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001362 break;
1363 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001364 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001365 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001366 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001367 send_callback = true;
1368 event = STREAM_CBK_EVENT_DRAIN_READY;
1369 break;
1370 default:
1371 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1372 break;
1373 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001374 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001375 out->offload_thread_blocked = false;
1376 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001377 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001378 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001379 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001380 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381 free(cmd);
1382 }
1383
1384 pthread_cond_signal(&out->cond);
1385 while (!list_empty(&out->offload_cmd_list)) {
1386 item = list_head(&out->offload_cmd_list);
1387 list_remove(item);
1388 free(node_to_item(item, struct offload_cmd, node));
1389 }
1390 pthread_mutex_unlock(&out->lock);
1391
1392 return NULL;
1393}
1394
1395static int create_offload_callback_thread(struct stream_out *out)
1396{
1397 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1398 list_init(&out->offload_cmd_list);
1399 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1400 offload_thread_loop, out);
1401 return 0;
1402}
1403
1404static int destroy_offload_callback_thread(struct stream_out *out)
1405{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001406 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001407 stop_compressed_output_l(out);
1408 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1409
1410 pthread_mutex_unlock(&out->lock);
1411 pthread_join(out->offload_thread, (void **) NULL);
1412 pthread_cond_destroy(&out->offload_cond);
1413
1414 return 0;
1415}
1416
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417static bool allow_hdmi_channel_config(struct audio_device *adev)
1418{
1419 struct listnode *node;
1420 struct audio_usecase *usecase;
1421 bool ret = true;
1422
1423 list_for_each(node, &adev->usecase_list) {
1424 usecase = node_to_item(node, struct audio_usecase, list);
1425 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1426 /*
1427 * If voice call is already existing, do not proceed further to avoid
1428 * disabling/enabling both RX and TX devices, CSD calls, etc.
1429 * Once the voice call done, the HDMI channels can be configured to
1430 * max channels of remaining use cases.
1431 */
1432 if (usecase->id == USECASE_VOICE_CALL) {
1433 ALOGD("%s: voice call is active, no change in HDMI channels",
1434 __func__);
1435 ret = false;
1436 break;
1437 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1438 ALOGD("%s: multi channel playback is active, "
1439 "no change in HDMI channels", __func__);
1440 ret = false;
1441 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001442 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001443 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001444 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1445 ", no change in HDMI channels", __func__,
1446 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001447 ret = false;
1448 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001449 }
1450 }
1451 }
1452 return ret;
1453}
1454
1455static int check_and_set_hdmi_channels(struct audio_device *adev,
1456 unsigned int channels)
1457{
1458 struct listnode *node;
1459 struct audio_usecase *usecase;
1460
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001461 unsigned int supported_channels = platform_edid_get_max_channels(
1462 adev->platform);
1463 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001464 /* Check if change in HDMI channel config is allowed */
1465 if (!allow_hdmi_channel_config(adev))
1466 return 0;
1467
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001468 if (channels > supported_channels)
1469 channels = supported_channels;
1470
Eric Laurent07eeafd2013-10-06 12:52:49 -07001471 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001472 ALOGD("%s: Requested channels are same as current channels(%d)",
1473 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001474 return 0;
1475 }
1476
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001477 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001478 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001479 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001480 adev->cur_hdmi_channels = channels;
1481
1482 /*
1483 * Deroute all the playback streams routed to HDMI so that
1484 * the back end is deactivated. Note that backend will not
1485 * be deactivated if any one stream is connected to it.
1486 */
1487 list_for_each(node, &adev->usecase_list) {
1488 usecase = node_to_item(node, struct audio_usecase, list);
1489 if (usecase->type == PCM_PLAYBACK &&
1490 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001491 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001492 }
1493 }
1494
1495 /*
1496 * Enable all the streams disabled above. Now the HDMI backend
1497 * will be activated with new channel configuration
1498 */
1499 list_for_each(node, &adev->usecase_list) {
1500 usecase = node_to_item(node, struct audio_usecase, list);
1501 if (usecase->type == PCM_PLAYBACK &&
1502 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001503 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001504 }
1505 }
1506
1507 return 0;
1508}
1509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510static int stop_output_stream(struct stream_out *out)
1511{
1512 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 struct audio_usecase *uc_info;
1514 struct audio_device *adev = out->dev;
1515
Eric Laurent994a6932013-07-17 11:51:42 -07001516 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001517 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 uc_info = get_usecase_from_list(adev, out->usecase);
1519 if (uc_info == NULL) {
1520 ALOGE("%s: Could not find the usecase (%d) in the list",
1521 __func__, out->usecase);
1522 return -EINVAL;
1523 }
1524
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001525 if (is_offload_usecase(out->usecase) &&
1526 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001527 if (adev->visualizer_stop_output != NULL)
1528 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001529
1530 audio_extn_dts_remove_state_notifier_node(out->usecase);
1531
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001532 if (adev->offload_effects_stop_output != NULL)
1533 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1534 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001535
Eric Laurent150dbfe2013-02-27 14:31:02 -08001536 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001537 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538
1539 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001540 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001542 list_remove(&uc_info->list);
1543 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001545 if (is_offload_usecase(out->usecase) &&
1546 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1547 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1548 ALOGV("Disable passthrough , reset mixer to pcm");
1549 /* NO_PASSTHROUGH */
1550 out->compr_config.codec->compr_passthr = 0;
1551 audio_extn_dolby_set_hdmi_config(adev, out);
1552 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1553 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001554 /* Must be called after removing the usecase from list */
1555 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1556 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1557
Eric Laurent994a6932013-07-17 11:51:42 -07001558 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 return ret;
1560}
1561
1562int start_output_stream(struct stream_out *out)
1563{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001565 int sink_channels = 0;
1566 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 struct audio_usecase *uc_info;
1568 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301569 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001571 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1572 ret = -EINVAL;
1573 goto error_config;
1574 }
1575
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301576 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1577 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1578 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301579
Naresh Tanniru80659832014-06-04 18:17:56 +05301580 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301581 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301582 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301583 goto error_config;
1584 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301585
Eric Laurentb23d5282013-05-14 15:27:20 -07001586 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 if (out->pcm_device_id < 0) {
1588 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1589 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001590 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001591 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 }
1593
1594 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001595
1596 if (!uc_info) {
1597 ret = -ENOMEM;
1598 goto error_config;
1599 }
1600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 uc_info->id = out->usecase;
1602 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001603 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604 uc_info->devices = out->devices;
1605 uc_info->in_snd_device = SND_DEVICE_NONE;
1606 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001607 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001608 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001609 if (is_offload_usecase(out->usecase)) {
1610 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001611 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1612 }
1613 }
Mingming Yin9c041392014-05-01 15:37:31 -07001614 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1615 if (!strncmp("true", prop_value, 4)) {
1616 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001617 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1618 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001619 check_and_set_hdmi_channels(adev, sink_channels);
1620 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001621 if (is_offload_usecase(out->usecase)) {
1622 unsigned int ch_count = out->compr_config.codec->ch_in;
1623 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1624 /* backend channel config for passthrough stream is stereo */
1625 ch_count = 2;
1626 check_and_set_hdmi_channels(adev, ch_count);
1627 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001628 check_and_set_hdmi_channels(adev, out->config.channels);
1629 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001630 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001631 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001632 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001634 select_devices(adev, out->usecase);
1635
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001636 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1637 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001638 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001639 unsigned int flags = PCM_OUT;
1640 unsigned int pcm_open_retry_count = 0;
1641 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1642 flags |= PCM_MMAP | PCM_NOIRQ;
1643 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1644 } else
1645 flags |= PCM_MONOTONIC;
1646
1647 while (1) {
1648 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1649 flags, &out->config);
1650 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1651 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1652 if (out->pcm != NULL) {
1653 pcm_close(out->pcm);
1654 out->pcm = NULL;
1655 }
1656 if (pcm_open_retry_count-- == 0) {
1657 ret = -EIO;
1658 goto error_open;
1659 }
1660 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1661 continue;
1662 }
1663 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001664 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001665
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001666 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1667 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001668
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001669 ALOGV("%s: pcm_prepare", __func__);
1670 if (pcm_is_ready(out->pcm)) {
1671 ret = pcm_prepare(out->pcm);
1672 if (ret < 0) {
1673 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1674 pcm_close(out->pcm);
1675 out->pcm = NULL;
1676 goto error_open;
1677 }
1678 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001680 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1681 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001683 out->compr = compress_open(adev->snd_card,
1684 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001685 COMPRESS_IN, &out->compr_config);
1686 if (out->compr && !is_compress_ready(out->compr)) {
1687 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1688 compress_close(out->compr);
1689 out->compr = NULL;
1690 ret = -EIO;
1691 goto error_open;
1692 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301693 /* compress_open sends params of the track, so reset the flag here */
1694 out->is_compr_metadata_avail = false;
1695
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001696 if (out->offload_callback)
1697 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001698
Fred Oh3f43e742015-03-04 18:42:34 -08001699 /* Since small bufs uses blocking writes, a write will be blocked
1700 for the default max poll time (20s) in the event of an SSR.
1701 Reduce the poll time to observe and deal with SSR faster.
1702 */
1703 if (out->use_small_bufs) {
1704 compress_set_max_poll_wait(out->compr, 1000);
1705 }
1706
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001707 audio_extn_dts_create_state_notifier_node(out->usecase);
1708 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1709 popcount(out->channel_mask),
1710 out->playback_started);
1711
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001712#ifdef DS1_DOLBY_DDP_ENABLED
1713 if (audio_extn_is_dolby_format(out->format))
1714 audio_extn_dolby_send_ddp_endp_params(adev);
1715#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001716 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1717 if (adev->visualizer_start_output != NULL)
1718 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1719 if (adev->offload_effects_start_output != NULL)
1720 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001721 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001722 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001724
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001725 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001730error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301731 /*
1732 * sleep 50ms to allow sufficient time for kernel
1733 * drivers to recover incases like SSR.
1734 */
1735 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001736 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737}
1738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739static int check_input_parameters(uint32_t sample_rate,
1740 audio_format_t format,
1741 int channel_count)
1742{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001743 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001745 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001746 !voice_extn_compress_voip_is_format_supported(format) &&
1747 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001748
1749 switch (channel_count) {
1750 case 1:
1751 case 2:
1752 case 6:
1753 break;
1754 default:
1755 ret = -EINVAL;
1756 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757
1758 switch (sample_rate) {
1759 case 8000:
1760 case 11025:
1761 case 12000:
1762 case 16000:
1763 case 22050:
1764 case 24000:
1765 case 32000:
1766 case 44100:
1767 case 48000:
1768 break;
1769 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001770 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 }
1772
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001773 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774}
1775
1776static size_t get_input_buffer_size(uint32_t sample_rate,
1777 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001778 int channel_count,
1779 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780{
1781 size_t size = 0;
1782
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001783 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1784 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001786 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001787 if (is_low_latency)
1788 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001789 /* ToDo: should use frame_size computed based on the format and
1790 channel_count here. */
1791 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001793 /* make sure the size is multiple of 32 bytes
1794 * At 48 kHz mono 16-bit PCM:
1795 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1796 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1797 */
1798 size += 0x1f;
1799 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001800
1801 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802}
1803
1804static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1805{
1806 struct stream_out *out = (struct stream_out *)stream;
1807
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809}
1810
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001811static int out_set_sample_rate(struct audio_stream *stream __unused,
1812 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813{
1814 return -ENOSYS;
1815}
1816
1817static size_t out_get_buffer_size(const struct audio_stream *stream)
1818{
1819 struct stream_out *out = (struct stream_out *)stream;
1820
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001821 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001823 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1824 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001826 return out->config.period_size *
1827 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828}
1829
1830static uint32_t out_get_channels(const struct audio_stream *stream)
1831{
1832 struct stream_out *out = (struct stream_out *)stream;
1833
1834 return out->channel_mask;
1835}
1836
1837static audio_format_t out_get_format(const struct audio_stream *stream)
1838{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 struct stream_out *out = (struct stream_out *)stream;
1840
1841 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842}
1843
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001844static int out_set_format(struct audio_stream *stream __unused,
1845 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846{
1847 return -ENOSYS;
1848}
1849
1850static int out_standby(struct audio_stream *stream)
1851{
1852 struct stream_out *out = (struct stream_out *)stream;
1853 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001854
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301855 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1856 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001857 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1858 /* Ignore standby in case of voip call because the voip output
1859 * stream is closed in adev_close_output_stream()
1860 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301861 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001862 return 0;
1863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001865 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001867 if (adev->adm_deregister_stream)
1868 adev->adm_deregister_stream(adev->adm_data, out->handle);
1869
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001870 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001872 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001873 if (out->pcm) {
1874 pcm_close(out->pcm);
1875 out->pcm = NULL;
1876 }
1877 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001878 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001879 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301880 out->send_next_track_params = false;
1881 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001882 out->gapless_mdata.encoder_delay = 0;
1883 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 if (out->compr != NULL) {
1885 compress_close(out->compr);
1886 out->compr = NULL;
1887 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001890 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 }
1892 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001893 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894 return 0;
1895}
1896
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001897static int out_dump(const struct audio_stream *stream __unused,
1898 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899{
1900 return 0;
1901}
1902
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001903static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1904{
1905 int ret = 0;
1906 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001907
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001908 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001909 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001910 return -EINVAL;
1911 }
1912
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301913 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001914
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001915 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1916 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301917 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001918 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001919 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1920 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301921 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001922 }
1923
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001924 ALOGV("%s new encoder delay %u and padding %u", __func__,
1925 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1926
1927 return 0;
1928}
1929
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001930static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1931{
1932 return out == adev->primary_output || out == adev->voice_tx_output;
1933}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1936{
1937 struct stream_out *out = (struct stream_out *)stream;
1938 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001939 struct audio_usecase *usecase;
1940 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 struct str_parms *parms;
1942 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001943 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001944 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945
sangwoobc677242013-08-08 16:53:43 +09001946 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301949 if (!parms)
1950 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001951 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1952 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001954 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001955 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001957 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301958 * When HDMI cable is unplugged/usb hs is disconnected the
1959 * music playback is paused and the policy manager sends routing=0
1960 * But the audioflingercontinues to write data until standby time
1961 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001962 * Avoid this by routing audio to speaker until standby.
1963 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301964 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1965 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001967 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1968 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001969 }
1970
1971 /*
1972 * select_devices() call below switches all the usecases on the same
1973 * backend to the new device. Refer to check_usecases_codec_backend() in
1974 * the select_devices(). But how do we undo this?
1975 *
1976 * For example, music playback is active on headset (deep-buffer usecase)
1977 * and if we go to ringtones and select a ringtone, low-latency usecase
1978 * will be started on headset+speaker. As we can't enable headset+speaker
1979 * and headset devices at the same time, select_devices() switches the music
1980 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1981 * So when the ringtone playback is completed, how do we undo the same?
1982 *
1983 * We are relying on the out_set_parameters() call on deep-buffer output,
1984 * once the ringtone playback is ended.
1985 * NOTE: We should not check if the current devices are same as new devices.
1986 * Because select_devices() must be called to switch back the music
1987 * playback to headset.
1988 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001989 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001990 out->devices = val;
1991
1992 if (!out->standby)
1993 select_devices(adev, out->usecase);
1994
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001995 if (output_drives_call(adev, out)) {
1996 if(!voice_is_in_call(adev)) {
1997 if (adev->mode == AUDIO_MODE_IN_CALL) {
1998 adev->current_call_output = out;
1999 ret = voice_start_call(adev);
2000 }
2001 } else {
2002 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002003 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002004 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002005 }
2006 }
2007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002009 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002011
2012 if (out == adev->primary_output) {
2013 pthread_mutex_lock(&adev->lock);
2014 audio_extn_set_parameters(adev, parms);
2015 pthread_mutex_unlock(&adev->lock);
2016 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002017 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002018 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002019 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002020
2021 audio_extn_dts_create_state_notifier_node(out->usecase);
2022 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2023 popcount(out->channel_mask),
2024 out->playback_started);
2025
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002026 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002027 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302030error:
Eric Laurent994a6932013-07-17 11:51:42 -07002031 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 return ret;
2033}
2034
2035static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2036{
2037 struct stream_out *out = (struct stream_out *)stream;
2038 struct str_parms *query = str_parms_create_str(keys);
2039 char *str;
2040 char value[256];
2041 struct str_parms *reply = str_parms_create();
2042 size_t i, j;
2043 int ret;
2044 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002045
2046 if (!query || !reply) {
2047 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2048 return NULL;
2049 }
2050
Eric Laurent994a6932013-07-17 11:51:42 -07002051 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2053 if (ret >= 0) {
2054 value[0] = '\0';
2055 i = 0;
2056 while (out->supported_channel_masks[i] != 0) {
2057 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2058 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2059 if (!first) {
2060 strcat(value, "|");
2061 }
2062 strcat(value, out_channels_name_to_enum_table[j].name);
2063 first = false;
2064 break;
2065 }
2066 }
2067 i++;
2068 }
2069 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2070 str = str_parms_to_str(reply);
2071 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002072 voice_extn_out_get_parameters(out, query, reply);
2073 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002074 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002075 free(str);
2076 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002077 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002079
2080 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2081 if (ret >= 0) {
2082 value[0] = '\0';
2083 i = 0;
2084 first = true;
2085 while (out->supported_formats[i] != 0) {
2086 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2087 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2088 if (!first) {
2089 strcat(value, "|");
2090 }
2091 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2092 first = false;
2093 break;
2094 }
2095 }
2096 i++;
2097 }
2098 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2099 str = str_parms_to_str(reply);
2100 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 str_parms_destroy(query);
2102 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002103 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 return str;
2105}
2106
2107static uint32_t out_get_latency(const struct audio_stream_out *stream)
2108{
2109 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002110 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111
Alexy Josephaa54c872014-12-03 02:46:47 -08002112 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002113 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002114 } else {
2115 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002117 }
2118
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302119 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002120 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121}
2122
2123static int out_set_volume(struct audio_stream_out *stream, float left,
2124 float right)
2125{
Eric Laurenta9024de2013-04-04 09:19:12 -07002126 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 int volume[2];
2128
Eric Laurenta9024de2013-04-04 09:19:12 -07002129 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2130 /* only take left channel into account: the API is for stereo anyway */
2131 out->muted = (left == 0.0f);
2132 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002133 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002134 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2135 /*
2136 * Set mute or umute on HDMI passthrough stream.
2137 * Only take left channel into account.
2138 * Mute is 0 and unmute 1
2139 */
2140 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2141 } else {
2142 char mixer_ctl_name[128];
2143 struct audio_device *adev = out->dev;
2144 struct mixer_ctl *ctl;
2145 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002146 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002147
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002148 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2149 "Compress Playback %d Volume", pcm_device_id);
2150 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2151 if (!ctl) {
2152 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2153 __func__, mixer_ctl_name);
2154 return -EINVAL;
2155 }
2156 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2157 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2158 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2159 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002161 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 return -ENOSYS;
2164}
2165
2166static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2167 size_t bytes)
2168{
2169 struct stream_out *out = (struct stream_out *)stream;
2170 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302171 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002172 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002174 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302175
Naresh Tanniru80659832014-06-04 18:17:56 +05302176 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002177 // increase written size during SSR to avoid mismatch
2178 // with the written frames count in AF
2179 if (!is_offload_usecase(out->usecase))
2180 out->written += bytes / (out->config.channels * sizeof(short));
2181
Naresh Tanniru80659832014-06-04 18:17:56 +05302182 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302183 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302184 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302185 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002186 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302187 //during SSR for compress usecase we should return error to flinger
2188 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2189 pthread_mutex_unlock(&out->lock);
2190 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302191 }
2192 }
2193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002195 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002196 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002197 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2198 ret = voice_extn_compress_voip_start_output_stream(out);
2199 else
2200 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002201 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002204 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 goto exit;
2206 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002207 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2208 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002211 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002212 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002213 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002214 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002215 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2216 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302217 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2218 ALOGD("copl(%p):send next track params in gapless", out);
2219 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2220 out->send_next_track_params = false;
2221 out->is_compr_metadata_avail = false;
2222 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002223 }
2224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302226 if (ret < 0)
2227 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002229 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302230 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302232 } else if (-ENETRESET == ret) {
2233 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2234 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2235 pthread_mutex_unlock(&out->lock);
2236 out_standby(&out->stream.common);
2237 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302239 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002241 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 out->playback_started = 1;
2243 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002244
2245 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2246 popcount(out->channel_mask),
2247 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 }
2249 pthread_mutex_unlock(&out->lock);
2250 return ret;
2251 } else {
2252 if (out->pcm) {
2253 if (out->muted)
2254 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002257
2258 if (adev->adm_request_focus)
2259 adev->adm_request_focus(adev->adm_data, out->handle);
2260
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002261 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2262 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2263 else
2264 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002265
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302266 if (ret < 0)
2267 ret = -errno;
2268 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002269 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002270
2271 if (adev->adm_abandon_focus)
2272 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002273 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 }
2275
2276exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302277 /* ToDo: There may be a corner case when SSR happens back to back during
2278 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302279 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302280 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302281 }
2282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283 pthread_mutex_unlock(&out->lock);
2284
2285 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002286 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002287 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302288 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302289 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302290 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302291 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302292 out->standby = true;
2293 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002295 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302296 out_get_sample_rate(&out->stream.common));
2297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 }
2299 return bytes;
2300}
2301
2302static int out_get_render_position(const struct audio_stream_out *stream,
2303 uint32_t *dsp_frames)
2304{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302306 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002307
2308 if (dsp_frames == NULL)
2309 return -EINVAL;
2310
2311 *dsp_frames = 0;
2312 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002313 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002314 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302316 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302318 if (ret < 0)
2319 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002320 ALOGVV("%s rendered frames %d sample_rate %d",
2321 __func__, *dsp_frames, out->sample_rate);
2322 }
2323 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302324 if (-ENETRESET == ret) {
2325 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2326 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2327 return -EINVAL;
2328 } else if(ret < 0) {
2329 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2330 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302331 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2332 /*
2333 * Handle corner case where compress session is closed during SSR
2334 * and timestamp is queried
2335 */
2336 ALOGE(" ERROR: sound card not active, return error");
2337 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302338 } else {
2339 return 0;
2340 }
Zhou Song32a556e2015-05-05 10:46:56 +08002341 } else if (audio_is_linear_pcm(out->format)) {
2342 *dsp_frames = out->written;
2343 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 } else
2345 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002348static int out_add_audio_effect(const struct audio_stream *stream __unused,
2349 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350{
2351 return 0;
2352}
2353
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002354static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2355 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356{
2357 return 0;
2358}
2359
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002360static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2361 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362{
2363 return -EINVAL;
2364}
2365
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002366static int out_get_presentation_position(const struct audio_stream_out *stream,
2367 uint64_t *frames, struct timespec *timestamp)
2368{
2369 struct stream_out *out = (struct stream_out *)stream;
2370 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002371 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002372
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002373 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002374
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002375 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002376 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302377 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002378 &out->sample_rate);
2379 ALOGVV("%s rendered frames %ld sample_rate %d",
2380 __func__, dsp_frames, out->sample_rate);
2381 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302382 if (ret < 0)
2383 ret = -errno;
2384 if (-ENETRESET == ret) {
2385 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2386 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2387 ret = -EINVAL;
2388 } else
2389 ret = 0;
2390
Eric Laurent949a0892013-09-20 09:20:13 -07002391 /* this is the best we can do */
2392 clock_gettime(CLOCK_MONOTONIC, timestamp);
2393 }
2394 } else {
2395 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002396 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002397 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2398 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002399 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002400 // This adjustment accounts for buffering after app processor.
2401 // It is based on estimated DSP latency per use case, rather than exact.
2402 signed_frames -=
2403 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2404
Eric Laurent949a0892013-09-20 09:20:13 -07002405 // It would be unusual for this value to be negative, but check just in case ...
2406 if (signed_frames >= 0) {
2407 *frames = signed_frames;
2408 ret = 0;
2409 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002410 }
2411 }
2412 }
2413
2414 pthread_mutex_unlock(&out->lock);
2415
2416 return ret;
2417}
2418
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419static int out_set_callback(struct audio_stream_out *stream,
2420 stream_callback_t callback, void *cookie)
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423
2424 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002425 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002426 out->offload_callback = callback;
2427 out->offload_cookie = cookie;
2428 pthread_mutex_unlock(&out->lock);
2429 return 0;
2430}
2431
2432static int out_pause(struct audio_stream_out* stream)
2433{
2434 struct stream_out *out = (struct stream_out *)stream;
2435 int status = -ENOSYS;
2436 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002437 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002438 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002439 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302441 struct audio_device *adev = out->dev;
2442 int snd_scard_state = get_snd_card_state(adev);
2443
2444 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2445 status = compress_pause(out->compr);
2446
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002448
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302449 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002450 audio_extn_dts_notify_playback_state(out->usecase, 0,
2451 out->sample_rate, popcount(out->channel_mask),
2452 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 }
2454 pthread_mutex_unlock(&out->lock);
2455 }
2456 return status;
2457}
2458
2459static int out_resume(struct audio_stream_out* stream)
2460{
2461 struct stream_out *out = (struct stream_out *)stream;
2462 int status = -ENOSYS;
2463 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002464 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002465 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002467 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302469 struct audio_device *adev = out->dev;
2470 int snd_scard_state = get_snd_card_state(adev);
2471
2472 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2473 status = compress_resume(out->compr);
2474
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002476
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302477 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002478 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2479 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 }
2481 pthread_mutex_unlock(&out->lock);
2482 }
2483 return status;
2484}
2485
2486static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2487{
2488 struct stream_out *out = (struct stream_out *)stream;
2489 int status = -ENOSYS;
2490 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002491 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002492 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2494 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2495 else
2496 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2497 pthread_mutex_unlock(&out->lock);
2498 }
2499 return status;
2500}
2501
2502static int out_flush(struct audio_stream_out* stream)
2503{
2504 struct stream_out *out = (struct stream_out *)stream;
2505 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002506 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002507 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002508 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002509 stop_compressed_output_l(out);
2510 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002511 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002512 return 0;
2513 }
2514 return -ENOSYS;
2515}
2516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517/** audio_stream_in implementation **/
2518static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2519{
2520 struct stream_in *in = (struct stream_in *)stream;
2521
2522 return in->config.rate;
2523}
2524
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002525static int in_set_sample_rate(struct audio_stream *stream __unused,
2526 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527{
2528 return -ENOSYS;
2529}
2530
2531static size_t in_get_buffer_size(const struct audio_stream *stream)
2532{
2533 struct stream_in *in = (struct stream_in *)stream;
2534
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002535 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2536 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002537 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2538 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002539
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002540 return in->config.period_size *
2541 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542}
2543
2544static uint32_t in_get_channels(const struct audio_stream *stream)
2545{
2546 struct stream_in *in = (struct stream_in *)stream;
2547
2548 return in->channel_mask;
2549}
2550
2551static audio_format_t in_get_format(const struct audio_stream *stream)
2552{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002553 struct stream_in *in = (struct stream_in *)stream;
2554
2555 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556}
2557
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002558static int in_set_format(struct audio_stream *stream __unused,
2559 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560{
2561 return -ENOSYS;
2562}
2563
2564static int in_standby(struct audio_stream *stream)
2565{
2566 struct stream_in *in = (struct stream_in *)stream;
2567 struct audio_device *adev = in->dev;
2568 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302569 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2570 stream, in->usecase, use_case_table[in->usecase]);
2571
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002572 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2573 /* Ignore standby in case of voip call because the voip input
2574 * stream is closed in adev_close_input_stream()
2575 */
2576 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2577 return status;
2578 }
2579
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002580 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002581 if (!in->standby && in->is_st_session) {
2582 ALOGD("%s: sound trigger pcm stop lab", __func__);
2583 audio_extn_sound_trigger_stop_lab(in);
2584 in->standby = 1;
2585 }
2586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002588 if (adev->adm_deregister_stream)
2589 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2590
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002591 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002593 if (in->pcm) {
2594 pcm_close(in->pcm);
2595 in->pcm = NULL;
2596 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002598 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 }
2600 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002601 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 return status;
2603}
2604
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002605static int in_dump(const struct audio_stream *stream __unused,
2606 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607{
2608 return 0;
2609}
2610
2611static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2612{
2613 struct stream_in *in = (struct stream_in *)stream;
2614 struct audio_device *adev = in->dev;
2615 struct str_parms *parms;
2616 char *str;
2617 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002618 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302620 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 parms = str_parms_create_str(kvpairs);
2622
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302623 if (!parms)
2624 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002625 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002626 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002627
2628 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2629 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 val = atoi(value);
2631 /* no audio source uses val == 0 */
2632 if ((in->source != val) && (val != 0)) {
2633 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002634 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2635 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2636 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2637 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002638 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002639 err = voice_extn_compress_voip_open_input_stream(in);
2640 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002641 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002642 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002643 }
2644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 }
2646 }
2647
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002648 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2649 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002651 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 in->device = val;
2653 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002654 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002655 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 }
2657 }
2658
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002659done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002661 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662
2663 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302664error:
Eric Laurent994a6932013-07-17 11:51:42 -07002665 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 return ret;
2667}
2668
2669static char* in_get_parameters(const struct audio_stream *stream,
2670 const char *keys)
2671{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002672 struct stream_in *in = (struct stream_in *)stream;
2673 struct str_parms *query = str_parms_create_str(keys);
2674 char *str;
2675 char value[256];
2676 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002677
2678 if (!query || !reply) {
2679 ALOGE("in_get_parameters: failed to create query or reply");
2680 return NULL;
2681 }
2682
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002683 ALOGV("%s: enter: keys - %s", __func__, keys);
2684
2685 voice_extn_in_get_parameters(in, query, reply);
2686
2687 str = str_parms_to_str(reply);
2688 str_parms_destroy(query);
2689 str_parms_destroy(reply);
2690
2691 ALOGV("%s: exit: returns - %s", __func__, str);
2692 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693}
2694
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002695static int in_set_gain(struct audio_stream_in *stream __unused,
2696 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697{
2698 return 0;
2699}
2700
2701static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2702 size_t bytes)
2703{
2704 struct stream_in *in = (struct stream_in *)stream;
2705 struct audio_device *adev = in->dev;
2706 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302707 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002709 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302710
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002711 if (in->is_st_session) {
2712 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2713 /* Read from sound trigger HAL */
2714 audio_extn_sound_trigger_read(in, buffer, bytes);
2715 pthread_mutex_unlock(&in->lock);
2716 return bytes;
2717 }
2718
2719 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2720 ALOGD(" %s: sound card is not active/SSR state", __func__);
2721 ret= -EIO;;
2722 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302723 }
2724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002726 pthread_mutex_lock(&adev->lock);
2727 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2728 ret = voice_extn_compress_voip_start_input_stream(in);
2729 else
2730 ret = start_input_stream(in);
2731 pthread_mutex_unlock(&adev->lock);
2732 if (ret != 0) {
2733 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 }
2735 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002736 if (adev->adm_register_input_stream)
2737 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002740 if (adev->adm_request_focus)
2741 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002744 if (audio_extn_ssr_get_enabled() &&
2745 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002746 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002747 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2748 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002749 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2750 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002751 else
2752 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302753 if (ret < 0)
2754 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 }
2756
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002757 if (adev->adm_abandon_focus)
2758 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 /*
2761 * Instead of writing zeroes here, we could trust the hardware
2762 * to always provide zeroes when muted.
2763 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302764 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2765 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 memset(buffer, 0, bytes);
2767
2768exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302769 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302770 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002771 if (-ENETRESET == ret)
2772 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 pthread_mutex_unlock(&in->lock);
2775
2776 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302777 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302778 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302779 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302780 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302781 in->standby = true;
2782 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302783 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002785 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002786 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302787 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 }
2789 return bytes;
2790}
2791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002792static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793{
2794 return 0;
2795}
2796
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002797static int add_remove_audio_effect(const struct audio_stream *stream,
2798 effect_handle_t effect,
2799 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002801 struct stream_in *in = (struct stream_in *)stream;
2802 int status = 0;
2803 effect_descriptor_t desc;
2804
2805 status = (*effect)->get_descriptor(effect, &desc);
2806 if (status != 0)
2807 return status;
2808
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002809 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002810 pthread_mutex_lock(&in->dev->lock);
2811 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2812 in->enable_aec != enable &&
2813 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2814 in->enable_aec = enable;
2815 if (!in->standby)
2816 select_devices(in->dev, in->usecase);
2817 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002818 if (in->enable_ns != enable &&
2819 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2820 in->enable_ns = enable;
2821 if (!in->standby)
2822 select_devices(in->dev, in->usecase);
2823 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002824 pthread_mutex_unlock(&in->dev->lock);
2825 pthread_mutex_unlock(&in->lock);
2826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 return 0;
2828}
2829
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002830static int in_add_audio_effect(const struct audio_stream *stream,
2831 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832{
Eric Laurent994a6932013-07-17 11:51:42 -07002833 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002834 return add_remove_audio_effect(stream, effect, true);
2835}
2836
2837static int in_remove_audio_effect(const struct audio_stream *stream,
2838 effect_handle_t effect)
2839{
Eric Laurent994a6932013-07-17 11:51:42 -07002840 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002841 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842}
2843
2844static int adev_open_output_stream(struct audio_hw_device *dev,
2845 audio_io_handle_t handle,
2846 audio_devices_t devices,
2847 audio_output_flags_t flags,
2848 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002849 struct audio_stream_out **stream_out,
2850 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851{
2852 struct audio_device *adev = (struct audio_device *)dev;
2853 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002854 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002855 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302858
2859 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2860 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002861 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302862 return -EINVAL;
2863 }
2864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2866
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302867 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2868 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2869 devices, flags, &out->stream);
2870
2871
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002872 if (!out) {
2873 return -ENOMEM;
2874 }
2875
Haynes Mathew George204045b2015-02-25 20:32:03 -08002876 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002877 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002878 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 if (devices == AUDIO_DEVICE_NONE)
2881 devices = AUDIO_DEVICE_OUT_SPEAKER;
2882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 out->flags = flags;
2884 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002885 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002886 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 out->sample_rate = config->sample_rate;
2888 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2889 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002890 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002891 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002892 out->non_blocking = 0;
2893 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894
2895 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002896 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2897 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002898 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2899 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2900
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002901 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002902 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2903 ret = read_hdmi_channel_masks(out);
2904
2905 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2906 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002907 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002908 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002909 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002910
2911 if (config->sample_rate == 0)
2912 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2913 if (config->channel_mask == 0)
2914 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2915
2916 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2919 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002921 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002923 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2924 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002925 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002926 ret = voice_extn_compress_voip_open_output_stream(out);
2927 if (ret != 0) {
2928 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2929 __func__, ret);
2930 goto error_open;
2931 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002932 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2933 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2936 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2937 ALOGE("%s: Unsupported Offload information", __func__);
2938 ret = -EINVAL;
2939 goto error_open;
2940 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002941
2942 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2943 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2944 ALOGV("read and update_pass through formats");
2945 ret = audio_extn_dolby_update_passt_formats(adev, out);
2946 if(ret != 0) {
2947 goto error_open;
2948 }
2949 if(config->offload_info.format == 0)
2950 config->offload_info.format = out->supported_formats[0];
2951 }
2952
Mingming Yin90310102013-11-13 16:57:00 -08002953 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002954 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002955 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 ret = -EINVAL;
2957 goto error_open;
2958 }
2959
2960 out->compr_config.codec = (struct snd_codec *)
2961 calloc(1, sizeof(struct snd_codec));
2962
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002963 if (!out->compr_config.codec) {
2964 ret = -ENOMEM;
2965 goto error_open;
2966 }
2967
vivek mehta0ea887a2015-08-26 14:01:20 -07002968 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2969 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2970 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2971 } else {
2972 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2973 out->usecase = get_offload_usecase(adev);
Mingming Yin21d60472015-09-30 13:56:25 -07002974
2975 out->stream.set_callback = out_set_callback;
2976 out->stream.pause = out_pause;
2977 out->stream.resume = out_resume;
2978 out->stream.drain = out_drain;
2979 out->stream.flush = out_flush;
vivek mehta0ea887a2015-08-26 14:01:20 -07002980 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002981 if (config->offload_info.channel_mask)
2982 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002983 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002984 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002985 config->offload_info.channel_mask = config->channel_mask;
2986 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002987 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002988 out->sample_rate = config->offload_info.sample_rate;
2989
Mingming Yin3ee55c62014-08-04 14:23:35 -07002990 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002991
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002992 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002993 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002994 audio_extn_dolby_get_snd_codec_id(adev, out,
2995 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002996 else
2997 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002999
3000 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3001 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003002 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003003 platform_get_pcm_offload_buffer_size(&config->offload_info);
3004 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3005 out->compr_config.fragment_size =
3006 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003007 } else {
3008 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003009 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003010 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3012 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003013 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003014 out->compr_config.codec->bit_rate =
3015 config->offload_info.bit_rate;
3016 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003017 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303019 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003020 /*TODO: Do we need to change it for passthrough */
3021 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022
Manish Dewangana6fc5442015-08-24 20:30:31 +05303023 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3024 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3025 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3026 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003027 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3028 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003029 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003030 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003031 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3032 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003033
Mingming Yin3ee55c62014-08-04 14:23:35 -07003034 if (out->bit_width == 24) {
3035 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3036 }
3037
Amit Shekhar6f461b12014-08-01 14:52:58 -07003038 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303039 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003040
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003041 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3042 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003043
Mingming Yin497419f2015-07-01 16:57:32 -07003044 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003045 //this flag is set from framework only if its for PCM formats
3046 //no need to check for PCM format again
3047 out->non_blocking = 0;
3048 out->use_small_bufs = true;
3049 ALOGI("Keep write blocking for small buff: non_blockling %d",
3050 out->non_blocking);
3051 }
3052
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003053 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303054 out->send_next_track_params = false;
3055 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003056 out->offload_state = OFFLOAD_STATE_IDLE;
3057 out->playback_started = 0;
3058
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003059 audio_extn_dts_create_state_notifier_node(out->usecase);
3060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 create_offload_callback_thread(out);
3062 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3063 __func__, config->offload_info.version,
3064 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003065 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003066 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003067 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3068 ret = voice_check_and_set_incall_music_usecase(adev, out);
3069 if (ret != 0) {
3070 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3071 __func__, ret);
3072 goto error_open;
3073 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003074 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3075 if (config->sample_rate == 0)
3076 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3077 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3078 config->sample_rate != 8000) {
3079 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3080 ret = -EINVAL;
3081 goto error_open;
3082 }
3083 out->sample_rate = config->sample_rate;
3084 out->config.rate = config->sample_rate;
3085 if (config->format == AUDIO_FORMAT_DEFAULT)
3086 config->format = AUDIO_FORMAT_PCM_16_BIT;
3087 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3088 config->format = AUDIO_FORMAT_PCM_16_BIT;
3089 ret = -EINVAL;
3090 goto error_open;
3091 }
3092 out->format = config->format;
3093 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3094 out->config = pcm_config_afe_proxy_playback;
3095 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003096 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3097 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3098 out->config = pcm_config_low_latency;
3099 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003100 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003101 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3103 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003104 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003105 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3106 format = AUDIO_FORMAT_PCM_16_BIT;
3107 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3108 out->config = pcm_config_deep_buffer;
3109 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003110 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003111 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003112 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003113 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003114 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003115 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 }
3117
Amit Shekhar1d896042014-10-03 13:16:09 -07003118 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3119 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003120 /* TODO remove this hardcoding and check why width is zero*/
3121 if (out->bit_width == 0)
3122 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003123 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3124 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003125 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003126 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003127 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3128 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3129 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003130 if(adev->primary_output == NULL)
3131 adev->primary_output = out;
3132 else {
3133 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003134 ret = -EEXIST;
3135 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003136 }
3137 }
3138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 /* Check if this usecase is already existing */
3140 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003141 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3142 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003145 ret = -EEXIST;
3146 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 }
3148 pthread_mutex_unlock(&adev->lock);
3149
3150 out->stream.common.get_sample_rate = out_get_sample_rate;
3151 out->stream.common.set_sample_rate = out_set_sample_rate;
3152 out->stream.common.get_buffer_size = out_get_buffer_size;
3153 out->stream.common.get_channels = out_get_channels;
3154 out->stream.common.get_format = out_get_format;
3155 out->stream.common.set_format = out_set_format;
3156 out->stream.common.standby = out_standby;
3157 out->stream.common.dump = out_dump;
3158 out->stream.common.set_parameters = out_set_parameters;
3159 out->stream.common.get_parameters = out_get_parameters;
3160 out->stream.common.add_audio_effect = out_add_audio_effect;
3161 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3162 out->stream.get_latency = out_get_latency;
3163 out->stream.set_volume = out_set_volume;
3164 out->stream.write = out_write;
3165 out->stream.get_render_position = out_get_render_position;
3166 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003167 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003170 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003171 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172
3173 config->format = out->stream.common.get_format(&out->stream.common);
3174 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3175 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3176
3177 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303178 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003179 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003180
3181 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3182 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3183 popcount(out->channel_mask), out->playback_started);
3184
Eric Laurent994a6932013-07-17 11:51:42 -07003185 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003187
3188error_open:
3189 free(out);
3190 *stream_out = NULL;
3191 ALOGD("%s: exit: ret %d", __func__, ret);
3192 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193}
3194
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003195static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 struct audio_stream_out *stream)
3197{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198 struct stream_out *out = (struct stream_out *)stream;
3199 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003200 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303202 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3203
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003204 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303205 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003206 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303207 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003208 if(ret != 0)
3209 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3210 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003211 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003212 out_standby(&stream->common);
3213
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003214 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003215 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003216 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003217 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003218 if (out->compr_config.codec != NULL)
3219 free(out->compr_config.codec);
3220 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003221
3222 if (adev->voice_tx_output == out)
3223 adev->voice_tx_output = NULL;
3224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003225 pthread_cond_destroy(&out->cond);
3226 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003228 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229}
3230
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003231static void close_compress_sessions(struct audio_device *adev)
3232{
Mingming Yin7b762e72015-03-04 13:47:32 -08003233 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303234 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003235 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003236 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303237
3238 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003239 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303240 if (is_offload_usecase(usecase->id)) {
3241 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003242 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3243 out = usecase->stream.out;
3244 pthread_mutex_unlock(&adev->lock);
3245 out_standby(&out->stream.common);
3246 pthread_mutex_lock(&adev->lock);
3247 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303248 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003249 }
3250 pthread_mutex_unlock(&adev->lock);
3251}
3252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3254{
3255 struct audio_device *adev = (struct audio_device *)dev;
3256 struct str_parms *parms;
3257 char *str;
3258 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003259 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003260 int ret;
3261 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003263 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303266 if (!parms)
3267 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003268 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3269 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303270 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303271 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303272 struct listnode *node;
3273 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303274 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303275 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003276 //close compress sessions on OFFLINE status
3277 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303278 } else if (strstr(snd_card_status, "ONLINE")) {
3279 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303280 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003281 //send dts hpx license if enabled
3282 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303283 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303284 }
3285
3286 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003287 status = voice_set_parameters(adev, parms);
3288 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003289 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003291 status = platform_set_parameters(adev->platform, parms);
3292 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003293 goto done;
3294
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003295 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3296 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003297 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3299 adev->bluetooth_nrec = true;
3300 else
3301 adev->bluetooth_nrec = false;
3302 }
3303
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003304 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3305 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3307 adev->screen_off = false;
3308 else
3309 adev->screen_off = true;
3310 }
3311
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003312 ret = str_parms_get_int(parms, "rotation", &val);
3313 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003314 bool reverse_speakers = false;
3315 switch(val) {
3316 // FIXME: note that the code below assumes that the speakers are in the correct placement
3317 // relative to the user when the device is rotated 90deg from its default rotation. This
3318 // assumption is device-specific, not platform-specific like this code.
3319 case 270:
3320 reverse_speakers = true;
3321 break;
3322 case 0:
3323 case 90:
3324 case 180:
3325 break;
3326 default:
3327 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003328 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003329 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003330 if (status == 0) {
3331 if (adev->speaker_lr_swap != reverse_speakers) {
3332 adev->speaker_lr_swap = reverse_speakers;
3333 // only update the selected device if there is active pcm playback
3334 struct audio_usecase *usecase;
3335 struct listnode *node;
3336 list_for_each(node, &adev->usecase_list) {
3337 usecase = node_to_item(node, struct audio_usecase, list);
3338 if (usecase->type == PCM_PLAYBACK) {
3339 select_devices(adev, usecase->id);
3340 break;
3341 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003342 }
3343 }
3344 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003345 }
3346
Mingming Yin514a8bc2014-07-29 15:22:21 -07003347 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3348 if (ret >= 0) {
3349 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3350 adev->bt_wb_speech_enabled = true;
3351 else
3352 adev->bt_wb_speech_enabled = false;
3353 }
3354
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003355 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3356 if (ret >= 0) {
3357 val = atoi(value);
3358 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3359 ALOGV("cache new edid");
3360 platform_cache_edid(adev->platform);
3361 }
3362 }
3363
3364 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3365 if (ret >= 0) {
3366 val = atoi(value);
3367 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3368 ALOGV("invalidate cached edid");
3369 platform_invalidate_edid(adev->platform);
3370 }
3371 }
3372
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003373 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003374
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003375done:
3376 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003377 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303378error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003379 ALOGV("%s: exit with code(%d)", __func__, status);
3380 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
3383static char* adev_get_parameters(const struct audio_hw_device *dev,
3384 const char *keys)
3385{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003386 struct audio_device *adev = (struct audio_device *)dev;
3387 struct str_parms *reply = str_parms_create();
3388 struct str_parms *query = str_parms_create_str(keys);
3389 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303390 char value[256] = {0};
3391 int ret = 0;
3392
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003393 if (!query || !reply) {
3394 ALOGE("adev_get_parameters: failed to create query or reply");
3395 return NULL;
3396 }
3397
Naresh Tannirud7205b62014-06-20 02:54:48 +05303398 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3399 sizeof(value));
3400 if (ret >=0) {
3401 int val = 1;
3402 pthread_mutex_lock(&adev->snd_card_status.lock);
3403 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3404 val = 0;
3405 pthread_mutex_unlock(&adev->snd_card_status.lock);
3406 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3407 goto exit;
3408 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003409
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003410 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003411 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003412 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003413 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303414 pthread_mutex_unlock(&adev->lock);
3415
Naresh Tannirud7205b62014-06-20 02:54:48 +05303416exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003417 str = str_parms_to_str(reply);
3418 str_parms_destroy(query);
3419 str_parms_destroy(reply);
3420
3421 ALOGV("%s: exit: returns - %s", __func__, str);
3422 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423}
3424
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003425static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426{
3427 return 0;
3428}
3429
3430static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3431{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003432 int ret;
3433 struct audio_device *adev = (struct audio_device *)dev;
3434 pthread_mutex_lock(&adev->lock);
3435 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003436 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003437 pthread_mutex_unlock(&adev->lock);
3438 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439}
3440
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003441static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3442 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443{
3444 return -ENOSYS;
3445}
3446
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003447static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3448 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449{
3450 return -ENOSYS;
3451}
3452
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003453static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3454 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455{
3456 return -ENOSYS;
3457}
3458
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003459static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3460 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461{
3462 return -ENOSYS;
3463}
3464
3465static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3466{
3467 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 pthread_mutex_lock(&adev->lock);
3470 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003471 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003473 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3474 voice_is_in_call(adev)) {
3475 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003476 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003477 adev->current_call_output = NULL;
3478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 }
3480 pthread_mutex_unlock(&adev->lock);
3481 return 0;
3482}
3483
3484static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3485{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003486 int ret;
3487
3488 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003489 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003490 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3491 pthread_mutex_unlock(&adev->lock);
3492
3493 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494}
3495
3496static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3497{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003498 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 return 0;
3500}
3501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003502static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 const struct audio_config *config)
3504{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003505 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003507 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3508 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509}
3510
3511static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003512 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 audio_devices_t devices,
3514 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003515 struct audio_stream_in **stream_in,
3516 audio_input_flags_t flags __unused,
3517 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003518 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519{
3520 struct audio_device *adev = (struct audio_device *)dev;
3521 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003522 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003523 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003524 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 *stream_in = NULL;
3527 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3528 return -EINVAL;
3529
3530 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003531
3532 if (!in) {
3533 ALOGE("failed to allocate input stream");
3534 return -ENOMEM;
3535 }
3536
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303537 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003538 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3539 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003541 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003542 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544 in->stream.common.get_sample_rate = in_get_sample_rate;
3545 in->stream.common.set_sample_rate = in_set_sample_rate;
3546 in->stream.common.get_buffer_size = in_get_buffer_size;
3547 in->stream.common.get_channels = in_get_channels;
3548 in->stream.common.get_format = in_get_format;
3549 in->stream.common.set_format = in_set_format;
3550 in->stream.common.standby = in_standby;
3551 in->stream.common.dump = in_dump;
3552 in->stream.common.set_parameters = in_set_parameters;
3553 in->stream.common.get_parameters = in_get_parameters;
3554 in->stream.common.add_audio_effect = in_add_audio_effect;
3555 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3556 in->stream.set_gain = in_set_gain;
3557 in->stream.read = in_read;
3558 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3559
3560 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003561 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 in->standby = 1;
3564 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003565 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003566 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567
3568 /* Update config params with the requested sample rate and channels */
3569 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003570 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3571 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3572 is_low_latency = true;
3573#if LOW_LATENCY_CAPTURE_USE_CASE
3574 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3575#endif
3576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003579 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003581 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303582 if (adev->mode != AUDIO_MODE_IN_CALL) {
3583 ret = -EINVAL;
3584 goto err_open;
3585 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003586 if (config->sample_rate == 0)
3587 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3588 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3589 config->sample_rate != 8000) {
3590 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3591 ret = -EINVAL;
3592 goto err_open;
3593 }
3594 if (config->format == AUDIO_FORMAT_DEFAULT)
3595 config->format = AUDIO_FORMAT_PCM_16_BIT;
3596 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3597 config->format = AUDIO_FORMAT_PCM_16_BIT;
3598 ret = -EINVAL;
3599 goto err_open;
3600 }
3601
3602 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3603 in->config = pcm_config_afe_proxy_record;
3604 in->config.channels = channel_count;
3605 in->config.rate = config->sample_rate;
3606 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003607 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003608 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003609 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3610 ret = -EINVAL;
3611 goto err_open;
3612 }
3613 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003614 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003615 }
Mingming Yine62d7842013-10-25 16:26:03 -07003616 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003617 audio_extn_compr_cap_format_supported(config->format) &&
3618 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003619 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003620 } else {
3621 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003622 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003623 buffer_size = get_input_buffer_size(config->sample_rate,
3624 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003625 channel_count,
3626 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003627 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003628 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3629 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3630 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3631 (in->config.rate == 8000 || in->config.rate == 16000) &&
3632 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3633 voice_extn_compress_voip_open_input_stream(in);
3634 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003635 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003637 /* This stream could be for sound trigger lab,
3638 get sound trigger pcm if present */
3639 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303640 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003643 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003644 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645
3646err_open:
3647 free(in);
3648 *stream_in = NULL;
3649 return ret;
3650}
3651
3652static void adev_close_input_stream(struct audio_hw_device *dev,
3653 struct audio_stream_in *stream)
3654{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003655 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003656 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003657 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303658
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303659 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003660
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303661 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003662 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303663
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003664 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303665 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003666 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303667 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003668 if (ret != 0)
3669 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3670 __func__, ret);
3671 } else
3672 in_standby(&stream->common);
3673
Mingming Yin7b762e72015-03-04 13:47:32 -08003674 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003675 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003676 audio_extn_ssr_deinit();
3677 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678
Mingming Yine62d7842013-10-25 16:26:03 -07003679 if(audio_extn_compr_cap_enabled() &&
3680 audio_extn_compr_cap_format_supported(in->config.format))
3681 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003682
3683 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 return;
3685}
3686
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003687static int adev_dump(const audio_hw_device_t *device __unused,
3688 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689{
3690 return 0;
3691}
3692
3693static int adev_close(hw_device_t *device)
3694{
3695 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003696
3697 if (!adev)
3698 return 0;
3699
3700 pthread_mutex_lock(&adev_init_lock);
3701
3702 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003703 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003704 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003705 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003706 audio_route_free(adev->audio_route);
3707 free(adev->snd_dev_ref_cnt);
3708 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003709 if (adev->adm_deinit)
3710 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003711 free(device);
3712 adev = NULL;
3713 }
3714 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 return 0;
3717}
3718
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003719/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3720 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3721 * just that it _might_ work.
3722 */
3723static int period_size_is_plausible_for_low_latency(int period_size)
3724{
3725 switch (period_size) {
3726 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003727 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003728 case 240:
3729 case 320:
3730 case 480:
3731 return 1;
3732 default:
3733 return 0;
3734 }
3735}
3736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737static int adev_open(const hw_module_t *module, const char *name,
3738 hw_device_t **device)
3739{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003740 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003742 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3744
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003745 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003746 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003747 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003748 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003749 ALOGD("%s: returning existing instance of adev", __func__);
3750 ALOGD("%s: exit", __func__);
3751 pthread_mutex_unlock(&adev_init_lock);
3752 return 0;
3753 }
3754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 adev = calloc(1, sizeof(struct audio_device));
3756
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003757 if (!adev) {
3758 pthread_mutex_unlock(&adev_init_lock);
3759 return -ENOMEM;
3760 }
3761
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003762 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3765 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3766 adev->device.common.module = (struct hw_module_t *)module;
3767 adev->device.common.close = adev_close;
3768
3769 adev->device.init_check = adev_init_check;
3770 adev->device.set_voice_volume = adev_set_voice_volume;
3771 adev->device.set_master_volume = adev_set_master_volume;
3772 adev->device.get_master_volume = adev_get_master_volume;
3773 adev->device.set_master_mute = adev_set_master_mute;
3774 adev->device.get_master_mute = adev_get_master_mute;
3775 adev->device.set_mode = adev_set_mode;
3776 adev->device.set_mic_mute = adev_set_mic_mute;
3777 adev->device.get_mic_mute = adev_get_mic_mute;
3778 adev->device.set_parameters = adev_set_parameters;
3779 adev->device.get_parameters = adev_get_parameters;
3780 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3781 adev->device.open_output_stream = adev_open_output_stream;
3782 adev->device.close_output_stream = adev_close_output_stream;
3783 adev->device.open_input_stream = adev_open_input_stream;
3784 adev->device.close_input_stream = adev_close_input_stream;
3785 adev->device.dump = adev_dump;
3786
3787 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003789 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003790 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003793 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003794 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003795 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003796 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003797 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003798 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003799 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303800
3801 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3802 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003804 adev->platform = platform_init(adev);
3805 if (!adev->platform) {
3806 free(adev->snd_dev_ref_cnt);
3807 free(adev);
3808 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3809 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003810 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003811 return -EINVAL;
3812 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003813
Naresh Tanniru4c630392014-05-12 01:05:52 +05303814 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3815
Eric Laurentc4aef752013-09-12 17:45:53 -07003816 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3817 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3818 if (adev->visualizer_lib == NULL) {
3819 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3820 } else {
3821 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3822 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003823 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003824 "visualizer_hal_start_output");
3825 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003826 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003827 "visualizer_hal_stop_output");
3828 }
3829 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003830 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003831 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003832
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003833 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3834 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3835 if (adev->offload_effects_lib == NULL) {
3836 ALOGE("%s: DLOPEN failed for %s", __func__,
3837 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3838 } else {
3839 ALOGV("%s: DLOPEN successful for %s", __func__,
3840 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3841 adev->offload_effects_start_output =
3842 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3843 "offload_effects_bundle_hal_start_output");
3844 adev->offload_effects_stop_output =
3845 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3846 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003847 adev->offload_effects_set_hpx_state =
3848 (int (*)(bool))dlsym(adev->offload_effects_lib,
3849 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303850 adev->offload_effects_get_parameters =
3851 (void (*)(struct str_parms *, struct str_parms *))
3852 dlsym(adev->offload_effects_lib,
3853 "offload_effects_bundle_get_parameters");
3854 adev->offload_effects_set_parameters =
3855 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3856 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003857 }
3858 }
3859
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003860 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3861 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3862 if (adev->adm_lib == NULL) {
3863 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3864 } else {
3865 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3866 adev->adm_init = (adm_init_t)
3867 dlsym(adev->adm_lib, "adm_init");
3868 adev->adm_deinit = (adm_deinit_t)
3869 dlsym(adev->adm_lib, "adm_deinit");
3870 adev->adm_register_input_stream = (adm_register_input_stream_t)
3871 dlsym(adev->adm_lib, "adm_register_input_stream");
3872 adev->adm_register_output_stream = (adm_register_output_stream_t)
3873 dlsym(adev->adm_lib, "adm_register_output_stream");
3874 adev->adm_deregister_stream = (adm_deregister_stream_t)
3875 dlsym(adev->adm_lib, "adm_deregister_stream");
3876 adev->adm_request_focus = (adm_request_focus_t)
3877 dlsym(adev->adm_lib, "adm_request_focus");
3878 adev->adm_abandon_focus = (adm_abandon_focus_t)
3879 dlsym(adev->adm_lib, "adm_abandon_focus");
3880 }
3881 }
3882
Mingming Yin514a8bc2014-07-29 15:22:21 -07003883 adev->bt_wb_speech_enabled = false;
3884
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003885 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 *device = &adev->device.common;
3887
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003888 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3889 &adev->streams_output_cfg_list);
3890
Kiran Kandi910e1862013-10-29 13:29:42 -07003891 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003892
3893 char value[PROPERTY_VALUE_MAX];
3894 int trial;
3895 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3896 trial = atoi(value);
3897 if (period_size_is_plausible_for_low_latency(trial)) {
3898 pcm_config_low_latency.period_size = trial;
3899 pcm_config_low_latency.start_threshold = trial / 4;
3900 pcm_config_low_latency.avail_min = trial / 4;
3901 configured_low_latency_capture_period_size = trial;
3902 }
3903 }
3904 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3905 trial = atoi(value);
3906 if (period_size_is_plausible_for_low_latency(trial)) {
3907 configured_low_latency_capture_period_size = trial;
3908 }
3909 }
3910
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003911 pthread_mutex_unlock(&adev_init_lock);
3912
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003913 if (adev->adm_init)
3914 adev->adm_data = adev->adm_init();
3915
Eric Laurent994a6932013-07-17 11:51:42 -07003916 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 return 0;
3918}
3919
3920static struct hw_module_methods_t hal_module_methods = {
3921 .open = adev_open,
3922};
3923
3924struct audio_module HAL_MODULE_INFO_SYM = {
3925 .common = {
3926 .tag = HARDWARE_MODULE_TAG,
3927 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3928 .hal_api_version = HARDWARE_HAL_API_VERSION,
3929 .id = AUDIO_HARDWARE_MODULE_ID,
3930 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003931 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932 .methods = &hal_module_methods,
3933 },
3934};