blob: 1183db02e4da2f17d064df16bf2f190f02ed1f44 [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);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700460 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
461 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);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700482 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
483 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 {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700540 ALOGV("%s: snd_device(%d: %s)", __func__,
541 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700542 /* due to the possibility of calibration overwrite between listen
543 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700544 audio_extn_sound_trigger_update_device_status(snd_device,
545 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530546 audio_extn_listen_update_device_status(snd_device,
547 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700548 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700549 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700550 audio_extn_sound_trigger_update_device_status(snd_device,
551 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530552 audio_extn_listen_update_device_status(snd_device,
553 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700554 return -EINVAL;
555 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300556 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700557 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559 return 0;
560}
561
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700562int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700563 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
566
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800567 if (snd_device < SND_DEVICE_MIN ||
568 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800569 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800570 return -EINVAL;
571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
573 ALOGE("%s: device ref cnt is already 0", __func__);
574 return -EINVAL;
575 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700578
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700579 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
580 ALOGE("%s: Invalid sound device returned", __func__);
581 return -EINVAL;
582 }
583
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700584 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700585 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700586 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800587 /* exit usb play back thread */
588 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
589 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
590 audio_extn_usb_stop_playback();
591
592 /* exit usb capture thread */
593 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700594 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800595
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800596 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700597 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
598 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
599 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
600 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700601 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700603 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300604 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700605
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200606 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700607 audio_extn_sound_trigger_update_device_status(snd_device,
608 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530609 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800610 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800613 return 0;
614}
615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616static void check_usecases_codec_backend(struct audio_device *adev,
617 struct audio_usecase *uc_info,
618 snd_device_t snd_device)
619{
620 struct listnode *node;
621 struct audio_usecase *usecase;
622 bool switch_device[AUDIO_USECASE_MAX];
623 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800624 int backend_idx = DEFAULT_CODEC_BACKEND;
625 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626
627 /*
628 * This function is to make sure that all the usecases that are active on
629 * the hardware codec backend are always routed to any one device that is
630 * handled by the hardware codec.
631 * For example, if low-latency and deep-buffer usecases are currently active
632 * on speaker and out_set_parameters(headset) is received on low-latency
633 * output, then we have to make sure deep-buffer is also switched to headset,
634 * because of the limitation that both the devices cannot be enabled
635 * at the same time as they share the same backend.
636 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700637 /*
638 * This call is to check if we need to force routing for a particular stream
639 * If there is a backend configuration change for the device when a
640 * new stream starts, then ADM needs to be closed and re-opened with the new
641 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800642 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700643 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800644 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
645 snd_device);
646 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800648 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800649 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 for (i = 0; i < AUDIO_USECASE_MAX; i++)
651 switch_device[i] = false;
652
653 list_for_each(node, &adev->usecase_list) {
654 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800655
656 if (usecase == uc_info)
657 continue;
658 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
659 ALOGV("%s: backend_idx: %d,"
660 "usecase_backend_idx: %d, curr device: %s, usecase device:"
661 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530662 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800663
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800664 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700665 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800666 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
667 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530668 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800669 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700670 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700671 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 switch_device[usecase->id] = true;
673 num_uc_to_switch++;
674 }
675 }
676
677 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700678 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530680 /* Make sure the previous devices to be disabled first and then enable the
681 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
684 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 }
687 }
688
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700689 list_for_each(node, &adev->usecase_list) {
690 usecase = node_to_item(node, struct audio_usecase, list);
691 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700692 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700693 }
694 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 /* Re-route all the usecases on the shared backend other than the
697 specified usecase to new snd devices */
698 list_for_each(node, &adev->usecase_list) {
699 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530700 /* Update the out_snd_device only for the usecases that are enabled here */
701 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
702 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530703 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 }
705 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 }
707}
708
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700709static void check_and_route_capture_usecases(struct audio_device *adev,
710 struct audio_usecase *uc_info,
711 snd_device_t snd_device)
712{
713 struct listnode *node;
714 struct audio_usecase *usecase;
715 bool switch_device[AUDIO_USECASE_MAX];
716 int i, num_uc_to_switch = 0;
717
718 /*
719 * This function is to make sure that all the active capture usecases
720 * are always routed to the same input sound device.
721 * For example, if audio-record and voice-call usecases are currently
722 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
723 * is received for voice call then we have to make sure that audio-record
724 * usecase is also switched to earpiece i.e. voice-dmic-ef,
725 * because of the limitation that two devices cannot be enabled
726 * at the same time if they share the same backend.
727 */
728 for (i = 0; i < AUDIO_USECASE_MAX; i++)
729 switch_device[i] = false;
730
731 list_for_each(node, &adev->usecase_list) {
732 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800733 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700735 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700736 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
737 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700738 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
740 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700741 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700742 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743 switch_device[usecase->id] = true;
744 num_uc_to_switch++;
745 }
746 }
747
748 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700749 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700750
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530751 /* Make sure the previous devices to be disabled first and then enable the
752 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700756 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800757 }
758 }
759
760 list_for_each(node, &adev->usecase_list) {
761 usecase = node_to_item(node, struct audio_usecase, list);
762 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700763 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 }
765 }
766
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 /* Re-route all the usecases on the shared backend other than the
768 specified usecase to new snd devices */
769 list_for_each(node, &adev->usecase_list) {
770 usecase = node_to_item(node, struct audio_usecase, list);
771 /* Update the in_snd_device only before enabling the audio route */
772 if (switch_device[usecase->id] ) {
773 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800774 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530775 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 }
777 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 }
779}
780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700782static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700784 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700785 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786
787 switch (channels) {
788 /*
789 * Do not handle stereo output in Multi-channel cases
790 * Stereo case is handled in normal playback path
791 */
792 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700793 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800799 break;
800 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700801 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
804 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
805 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
806 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
807 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 break;
809 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700810 ALOGE("HDMI does not support multi channel playback");
811 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812 break;
813 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700814 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815}
816
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800817audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
818 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700819{
820 struct audio_usecase *usecase;
821 struct listnode *node;
822
823 list_for_each(node, &adev->usecase_list) {
824 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800825 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700826 ALOGV("%s: usecase id %d", __func__, usecase->id);
827 return usecase->id;
828 }
829 }
830 return USECASE_INVALID;
831}
832
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700833struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700834 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835{
836 struct audio_usecase *usecase;
837 struct listnode *node;
838
839 list_for_each(node, &adev->usecase_list) {
840 usecase = node_to_item(node, struct audio_usecase, list);
841 if (usecase->id == uc_id)
842 return usecase;
843 }
844 return NULL;
845}
846
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800849 snd_device_t out_snd_device = SND_DEVICE_NONE;
850 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 struct audio_usecase *usecase = NULL;
852 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800853 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800854 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800855 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800856 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800858
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 usecase = get_usecase_from_list(adev, uc_id);
860 if (usecase == NULL) {
861 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
862 return -EINVAL;
863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800865 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800866 (usecase->type == VOIP_CALL) ||
867 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800869 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700870 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 usecase->devices = usecase->stream.out->devices;
872 } else {
873 /*
874 * If the voice call is active, use the sound devices of voice call usecase
875 * so that it would not result any device switch. All the usecases will
876 * be switched to new device when select_devices() is called for voice call
877 * usecase. This is to avoid switching devices for voice call when
878 * check_usecases_codec_backend() is called below.
879 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700880 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700881 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800882 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
884 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 in_snd_device = vc_usecase->in_snd_device;
886 out_snd_device = vc_usecase->out_snd_device;
887 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800888 } else if (voice_extn_compress_voip_is_active(adev)) {
889 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700890 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530891 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700892 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800893 in_snd_device = voip_usecase->in_snd_device;
894 out_snd_device = voip_usecase->out_snd_device;
895 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800896 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800897 hfp_ucid = audio_extn_hfp_get_usecase();
898 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700899 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800900 in_snd_device = hfp_usecase->in_snd_device;
901 out_snd_device = hfp_usecase->out_snd_device;
902 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 }
904 if (usecase->type == PCM_PLAYBACK) {
905 usecase->devices = usecase->stream.out->devices;
906 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700907 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700908 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800909 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700910 if (usecase->stream.out == adev->primary_output &&
911 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800912 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700913 select_devices(adev, adev->active_input->usecase);
914 }
915 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 } else if (usecase->type == PCM_CAPTURE) {
917 usecase->devices = usecase->stream.in->device;
918 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700919 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530921 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
922 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
923 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
924 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700925 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700926 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700927 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
928 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700929 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700930 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700931 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700932 }
933 }
934
935 if (out_snd_device == usecase->out_snd_device &&
936 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 return 0;
938 }
939
sangwoobc677242013-08-08 16:53:43 +0900940 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700941 out_snd_device, platform_get_snd_device_name(out_snd_device),
942 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 /*
945 * Limitation: While in call, to do a device switch we need to disable
946 * and enable both RX and TX devices though one of them is same as current
947 * device.
948 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700949 if ((usecase->type == VOICE_CALL) &&
950 (usecase->in_snd_device != SND_DEVICE_NONE) &&
951 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700953 }
954
955 if (((usecase->type == VOICE_CALL) ||
956 (usecase->type == VOIP_CALL)) &&
957 (usecase->out_snd_device != SND_DEVICE_NONE)) {
958 /* Disable sidetone only if voice/voip call already exists */
959 if (voice_is_call_state_active(adev) ||
960 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700961 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800962 }
963
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 /* Disable current sound devices */
965 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700966 disable_audio_route(adev, usecase);
967 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 }
969
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700971 disable_audio_route(adev, usecase);
972 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 }
974
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800975 /* Applicable only on the targets that has external modem.
976 * New device information should be sent to modem before enabling
977 * the devices to reduce in-call device switch time.
978 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700979 if ((usecase->type == VOICE_CALL) &&
980 (usecase->in_snd_device != SND_DEVICE_NONE) &&
981 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800982 status = platform_switch_voice_call_enable_device_config(adev->platform,
983 out_snd_device,
984 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700985 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800986
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 /* Enable new sound devices */
988 if (out_snd_device != SND_DEVICE_NONE) {
989 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
990 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700991 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 }
993
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700994 if (in_snd_device != SND_DEVICE_NONE) {
995 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700996 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700997 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998
Avinash Vaish71a8b972014-07-24 15:36:33 +0530999 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001000 status = platform_switch_voice_call_device_post(adev->platform,
1001 out_snd_device,
1002 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301003 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001004 /* Enable sidetone only if voice/voip call already exists */
1005 if (voice_is_call_state_active(adev) ||
1006 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001007 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301008 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001009
sangwoo170731f2013-06-08 15:36:36 +09001010 usecase->in_snd_device = in_snd_device;
1011 usecase->out_snd_device = out_snd_device;
1012
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001014 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301015 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001016 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301017 usecase->stream.out->flags,
1018 usecase->stream.out->format,
1019 usecase->stream.out->sample_rate,
1020 usecase->stream.out->bit_width,
1021 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001022 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301023 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001024
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001025 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001026
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001027 /* Applicable only on the targets that has external modem.
1028 * Enable device command should be sent to modem only after
1029 * enabling voice call mixer controls
1030 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001031 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001032 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1033 out_snd_device,
1034 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301035 ALOGD("%s: done",__func__);
1036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037 return status;
1038}
1039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040static int stop_input_stream(struct stream_in *in)
1041{
1042 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 struct audio_usecase *uc_info;
1044 struct audio_device *adev = in->dev;
1045
Eric Laurentc8400632013-02-14 19:04:54 -08001046 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
Eric Laurent994a6932013-07-17 11:51:42 -07001048 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050 uc_info = get_usecase_from_list(adev, in->usecase);
1051 if (uc_info == NULL) {
1052 ALOGE("%s: Could not find the usecase (%d) in the list",
1053 __func__, in->usecase);
1054 return -EINVAL;
1055 }
1056
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001057 /* Close in-call recording streams */
1058 voice_check_and_stop_incall_rec_usecase(adev, in);
1059
Eric Laurent150dbfe2013-02-27 14:31:02 -08001060 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001061 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062
1063 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001064 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001066 list_remove(&uc_info->list);
1067 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068
Eric Laurent994a6932013-07-17 11:51:42 -07001069 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 return ret;
1071}
1072
1073int start_input_stream(struct stream_in *in)
1074{
1075 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001076 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 struct audio_usecase *uc_info;
1078 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301079 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080
Mingming Yin2664a5b2015-09-03 10:53:11 -07001081 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1082 if (get_usecase_from_list(adev, usecase) == NULL)
1083 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301084 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1085 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001086
Naresh Tanniru80659832014-06-04 18:17:56 +05301087
1088 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301090 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301091 goto error_config;
1092 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301093
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001094 /* Check if source matches incall recording usecase criteria */
1095 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1096 if (ret)
1097 goto error_config;
1098 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001099 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1100
1101 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1102 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1103 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1104 goto error_config;
1105 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001106
Eric Laurentb23d5282013-05-14 15:27:20 -07001107 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 if (in->pcm_device_id < 0) {
1109 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1110 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001111 ret = -EINVAL;
1112 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114
1115 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001117
1118 if (!uc_info) {
1119 ret = -ENOMEM;
1120 goto error_config;
1121 }
1122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 uc_info->id = in->usecase;
1124 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001125 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 uc_info->devices = in->device;
1127 uc_info->in_snd_device = SND_DEVICE_NONE;
1128 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001130 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301131 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133
Eric Laurentc8400632013-02-14 19:04:54 -08001134 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001135 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1136
1137 unsigned int flags = PCM_IN;
1138 unsigned int pcm_open_retry_count = 0;
1139
1140 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1141 flags |= PCM_MMAP | PCM_NOIRQ;
1142 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1143 }
1144
1145 while (1) {
1146 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1147 flags, &in->config);
1148 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1149 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1150 if (in->pcm != NULL) {
1151 pcm_close(in->pcm);
1152 in->pcm = NULL;
1153 }
1154 if (pcm_open_retry_count-- == 0) {
1155 ret = -EIO;
1156 goto error_open;
1157 }
1158 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1159 continue;
1160 }
1161 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301163 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301164
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001165 ALOGV("%s: pcm_prepare start", __func__);
1166 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -07001167 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001168
Eric Laurentc8400632013-02-14 19:04:54 -08001169 return ret;
1170
1171error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301173 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001174
1175error_config:
1176 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301177 /*
1178 * sleep 50ms to allow sufficient time for kernel
1179 * drivers to recover incases like SSR.
1180 */
1181 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001183
1184 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185}
1186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001187/* must be called with out->lock locked */
1188static int send_offload_cmd_l(struct stream_out* out, int command)
1189{
1190 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1191
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001192 if (!cmd) {
1193 ALOGE("failed to allocate mem for command 0x%x", command);
1194 return -ENOMEM;
1195 }
1196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001197 ALOGVV("%s %d", __func__, command);
1198
1199 cmd->cmd = command;
1200 list_add_tail(&out->offload_cmd_list, &cmd->node);
1201 pthread_cond_signal(&out->offload_cond);
1202 return 0;
1203}
1204
1205/* must be called iwth out->lock locked */
1206static void stop_compressed_output_l(struct stream_out *out)
1207{
1208 out->offload_state = OFFLOAD_STATE_IDLE;
1209 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001210 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001211 if (out->compr != NULL) {
1212 compress_stop(out->compr);
1213 while (out->offload_thread_blocked) {
1214 pthread_cond_wait(&out->cond, &out->lock);
1215 }
1216 }
1217}
1218
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001219bool is_offload_usecase(audio_usecase_t uc_id)
1220{
1221 unsigned int i;
1222 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1223 if (uc_id == offload_usecases[i])
1224 return true;
1225 }
1226 return false;
1227}
1228
1229static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1230{
1231 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1232 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1233 char value[PROPERTY_VALUE_MAX] = {0};
1234
1235 property_get("audio.offload.multiple.enabled", value, NULL);
1236 if (!(atoi(value) || !strncmp("true", value, 4)))
1237 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1238
1239 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1240 for (i = 0; i < num_usecase; i++) {
1241 if (!(adev->offload_usecases_state & (0x1<<i))) {
1242 adev->offload_usecases_state |= 0x1 << i;
1243 ret = offload_usecases[i];
1244 break;
1245 }
1246 }
1247 ALOGV("%s: offload usecase is %d", __func__, ret);
1248 return ret;
1249}
1250
1251static void free_offload_usecase(struct audio_device *adev,
1252 audio_usecase_t uc_id)
1253{
1254 unsigned int i;
1255 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1256 if (offload_usecases[i] == uc_id) {
1257 adev->offload_usecases_state &= ~(0x1<<i);
1258 break;
1259 }
1260 }
1261 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1262}
1263
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001264static void *offload_thread_loop(void *context)
1265{
1266 struct stream_out *out = (struct stream_out *) context;
1267 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001268 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001269
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001270 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1271 set_sched_policy(0, SP_FOREGROUND);
1272 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1273
1274 ALOGV("%s", __func__);
1275 pthread_mutex_lock(&out->lock);
1276 for (;;) {
1277 struct offload_cmd *cmd = NULL;
1278 stream_callback_event_t event;
1279 bool send_callback = false;
1280
1281 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1282 __func__, list_empty(&out->offload_cmd_list),
1283 out->offload_state);
1284 if (list_empty(&out->offload_cmd_list)) {
1285 ALOGV("%s SLEEPING", __func__);
1286 pthread_cond_wait(&out->offload_cond, &out->lock);
1287 ALOGV("%s RUNNING", __func__);
1288 continue;
1289 }
1290
1291 item = list_head(&out->offload_cmd_list);
1292 cmd = node_to_item(item, struct offload_cmd, node);
1293 list_remove(item);
1294
1295 ALOGVV("%s STATE %d CMD %d out->compr %p",
1296 __func__, out->offload_state, cmd->cmd, out->compr);
1297
1298 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1299 free(cmd);
1300 break;
1301 }
1302
1303 if (out->compr == NULL) {
1304 ALOGE("%s: Compress handle is NULL", __func__);
1305 pthread_cond_signal(&out->cond);
1306 continue;
1307 }
1308 out->offload_thread_blocked = true;
1309 pthread_mutex_unlock(&out->lock);
1310 send_callback = false;
1311 switch(cmd->cmd) {
1312 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001313 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001314 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001315 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001316 send_callback = true;
1317 event = STREAM_CBK_EVENT_WRITE_READY;
1318 break;
1319 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001320 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301321 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001322 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301323 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001324 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301325 if (ret < 0)
1326 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301327 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301328 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001329 compress_drain(out->compr);
1330 else
1331 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301332 if (ret != -ENETRESET) {
1333 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301334 pthread_mutex_lock(&out->lock);
1335 out->send_new_metadata = 1;
1336 out->send_next_track_params = true;
1337 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301338 event = STREAM_CBK_EVENT_DRAIN_READY;
1339 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1340 } else
1341 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001342 break;
1343 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001344 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001345 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001346 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 send_callback = true;
1348 event = STREAM_CBK_EVENT_DRAIN_READY;
1349 break;
1350 default:
1351 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1352 break;
1353 }
1354 pthread_mutex_lock(&out->lock);
1355 out->offload_thread_blocked = false;
1356 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001357 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001358 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001359 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001360 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001361 free(cmd);
1362 }
1363
1364 pthread_cond_signal(&out->cond);
1365 while (!list_empty(&out->offload_cmd_list)) {
1366 item = list_head(&out->offload_cmd_list);
1367 list_remove(item);
1368 free(node_to_item(item, struct offload_cmd, node));
1369 }
1370 pthread_mutex_unlock(&out->lock);
1371
1372 return NULL;
1373}
1374
1375static int create_offload_callback_thread(struct stream_out *out)
1376{
1377 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1378 list_init(&out->offload_cmd_list);
1379 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1380 offload_thread_loop, out);
1381 return 0;
1382}
1383
1384static int destroy_offload_callback_thread(struct stream_out *out)
1385{
1386 pthread_mutex_lock(&out->lock);
1387 stop_compressed_output_l(out);
1388 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1389
1390 pthread_mutex_unlock(&out->lock);
1391 pthread_join(out->offload_thread, (void **) NULL);
1392 pthread_cond_destroy(&out->offload_cond);
1393
1394 return 0;
1395}
1396
Eric Laurent07eeafd2013-10-06 12:52:49 -07001397static bool allow_hdmi_channel_config(struct audio_device *adev)
1398{
1399 struct listnode *node;
1400 struct audio_usecase *usecase;
1401 bool ret = true;
1402
1403 list_for_each(node, &adev->usecase_list) {
1404 usecase = node_to_item(node, struct audio_usecase, list);
1405 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1406 /*
1407 * If voice call is already existing, do not proceed further to avoid
1408 * disabling/enabling both RX and TX devices, CSD calls, etc.
1409 * Once the voice call done, the HDMI channels can be configured to
1410 * max channels of remaining use cases.
1411 */
1412 if (usecase->id == USECASE_VOICE_CALL) {
1413 ALOGD("%s: voice call is active, no change in HDMI channels",
1414 __func__);
1415 ret = false;
1416 break;
1417 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1418 ALOGD("%s: multi channel playback is active, "
1419 "no change in HDMI channels", __func__);
1420 ret = false;
1421 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001422 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001423 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001424 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1425 ", no change in HDMI channels", __func__,
1426 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001427 ret = false;
1428 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001429 }
1430 }
1431 }
1432 return ret;
1433}
1434
1435static int check_and_set_hdmi_channels(struct audio_device *adev,
1436 unsigned int channels)
1437{
1438 struct listnode *node;
1439 struct audio_usecase *usecase;
1440
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001441 unsigned int supported_channels = platform_edid_get_max_channels(
1442 adev->platform);
1443 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001444 /* Check if change in HDMI channel config is allowed */
1445 if (!allow_hdmi_channel_config(adev))
1446 return 0;
1447
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001448 if (channels > supported_channels)
1449 channels = supported_channels;
1450
Eric Laurent07eeafd2013-10-06 12:52:49 -07001451 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001452 ALOGD("%s: Requested channels are same as current channels(%d)",
1453 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001454 return 0;
1455 }
1456
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001457 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001458 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001459 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001460 adev->cur_hdmi_channels = channels;
1461
1462 /*
1463 * Deroute all the playback streams routed to HDMI so that
1464 * the back end is deactivated. Note that backend will not
1465 * be deactivated if any one stream is connected to it.
1466 */
1467 list_for_each(node, &adev->usecase_list) {
1468 usecase = node_to_item(node, struct audio_usecase, list);
1469 if (usecase->type == PCM_PLAYBACK &&
1470 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001471 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001472 }
1473 }
1474
1475 /*
1476 * Enable all the streams disabled above. Now the HDMI backend
1477 * will be activated with new channel configuration
1478 */
1479 list_for_each(node, &adev->usecase_list) {
1480 usecase = node_to_item(node, struct audio_usecase, list);
1481 if (usecase->type == PCM_PLAYBACK &&
1482 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001483 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001484 }
1485 }
1486
1487 return 0;
1488}
1489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490static int stop_output_stream(struct stream_out *out)
1491{
1492 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493 struct audio_usecase *uc_info;
1494 struct audio_device *adev = out->dev;
1495
Eric Laurent994a6932013-07-17 11:51:42 -07001496 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 uc_info = get_usecase_from_list(adev, out->usecase);
1499 if (uc_info == NULL) {
1500 ALOGE("%s: Could not find the usecase (%d) in the list",
1501 __func__, out->usecase);
1502 return -EINVAL;
1503 }
1504
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001505 if (is_offload_usecase(out->usecase) &&
1506 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001507 if (adev->visualizer_stop_output != NULL)
1508 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001509
1510 audio_extn_dts_remove_state_notifier_node(out->usecase);
1511
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001512 if (adev->offload_effects_stop_output != NULL)
1513 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1514 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001515
Eric Laurent150dbfe2013-02-27 14:31:02 -08001516 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001517 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518
1519 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001520 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001522 list_remove(&uc_info->list);
1523 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001525 if (is_offload_usecase(out->usecase) &&
1526 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1527 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1528 ALOGV("Disable passthrough , reset mixer to pcm");
1529 /* NO_PASSTHROUGH */
1530 out->compr_config.codec->compr_passthr = 0;
1531 audio_extn_dolby_set_hdmi_config(adev, out);
1532 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1533 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001534 /* Must be called after removing the usecase from list */
1535 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1536 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1537
Eric Laurent994a6932013-07-17 11:51:42 -07001538 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 return ret;
1540}
1541
1542int start_output_stream(struct stream_out *out)
1543{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001545 int sink_channels = 0;
1546 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 struct audio_usecase *uc_info;
1548 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301549 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001551 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1552 ret = -EINVAL;
1553 goto error_config;
1554 }
1555
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301556 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1557 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1558 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301559
Naresh Tanniru80659832014-06-04 18:17:56 +05301560 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301561 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301562 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301563 goto error_config;
1564 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301565
Eric Laurentb23d5282013-05-14 15:27:20 -07001566 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 if (out->pcm_device_id < 0) {
1568 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1569 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001570 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001571 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 }
1573
1574 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001575
1576 if (!uc_info) {
1577 ret = -ENOMEM;
1578 goto error_config;
1579 }
1580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581 uc_info->id = out->usecase;
1582 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001583 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584 uc_info->devices = out->devices;
1585 uc_info->in_snd_device = SND_DEVICE_NONE;
1586 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001587 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001588 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001589 if (is_offload_usecase(out->usecase)) {
1590 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001591 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1592 }
1593 }
Mingming Yin9c041392014-05-01 15:37:31 -07001594 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1595 if (!strncmp("true", prop_value, 4)) {
1596 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001597 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1598 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001599 check_and_set_hdmi_channels(adev, sink_channels);
1600 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001601 if (is_offload_usecase(out->usecase)) {
1602 unsigned int ch_count = out->compr_config.codec->ch_in;
1603 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1604 /* backend channel config for passthrough stream is stereo */
1605 ch_count = 2;
1606 check_and_set_hdmi_channels(adev, ch_count);
1607 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001608 check_and_set_hdmi_channels(adev, out->config.channels);
1609 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001610 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001611 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001612 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001614 select_devices(adev, out->usecase);
1615
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001616 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1617 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001618 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001619 unsigned int flags = PCM_OUT;
1620 unsigned int pcm_open_retry_count = 0;
1621 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1622 flags |= PCM_MMAP | PCM_NOIRQ;
1623 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1624 } else
1625 flags |= PCM_MONOTONIC;
1626
1627 while (1) {
1628 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1629 flags, &out->config);
1630 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1631 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1632 if (out->pcm != NULL) {
1633 pcm_close(out->pcm);
1634 out->pcm = NULL;
1635 }
1636 if (pcm_open_retry_count-- == 0) {
1637 ret = -EIO;
1638 goto error_open;
1639 }
1640 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1641 continue;
1642 }
1643 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001644 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001645
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001646 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1647 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001648
1649 ALOGV("%s: pcm_prepare start", __func__);
1650 if (pcm_is_ready(out->pcm))
1651 pcm_prepare(out->pcm);
1652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001653 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001654 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1655 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001657 out->compr = compress_open(adev->snd_card,
1658 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001659 COMPRESS_IN, &out->compr_config);
1660 if (out->compr && !is_compress_ready(out->compr)) {
1661 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1662 compress_close(out->compr);
1663 out->compr = NULL;
1664 ret = -EIO;
1665 goto error_open;
1666 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301667 /* compress_open sends params of the track, so reset the flag here */
1668 out->is_compr_metadata_avail = false;
1669
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 if (out->offload_callback)
1671 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001672
Fred Oh3f43e742015-03-04 18:42:34 -08001673 /* Since small bufs uses blocking writes, a write will be blocked
1674 for the default max poll time (20s) in the event of an SSR.
1675 Reduce the poll time to observe and deal with SSR faster.
1676 */
1677 if (out->use_small_bufs) {
1678 compress_set_max_poll_wait(out->compr, 1000);
1679 }
1680
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001681 audio_extn_dts_create_state_notifier_node(out->usecase);
1682 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1683 popcount(out->channel_mask),
1684 out->playback_started);
1685
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001686#ifdef DS1_DOLBY_DDP_ENABLED
1687 if (audio_extn_is_dolby_format(out->format))
1688 audio_extn_dolby_send_ddp_endp_params(adev);
1689#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001690 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1691 if (adev->visualizer_start_output != NULL)
1692 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1693 if (adev->offload_effects_start_output != NULL)
1694 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001695 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001698
Eric Laurent994a6932013-07-17 11:51:42 -07001699 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001702error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001704error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301705 /*
1706 * sleep 50ms to allow sufficient time for kernel
1707 * drivers to recover incases like SSR.
1708 */
1709 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001710 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711}
1712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713static int check_input_parameters(uint32_t sample_rate,
1714 audio_format_t format,
1715 int channel_count)
1716{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001717 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001719 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001720 !voice_extn_compress_voip_is_format_supported(format) &&
1721 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001722
1723 switch (channel_count) {
1724 case 1:
1725 case 2:
1726 case 6:
1727 break;
1728 default:
1729 ret = -EINVAL;
1730 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731
1732 switch (sample_rate) {
1733 case 8000:
1734 case 11025:
1735 case 12000:
1736 case 16000:
1737 case 22050:
1738 case 24000:
1739 case 32000:
1740 case 44100:
1741 case 48000:
1742 break;
1743 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001744 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 }
1746
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001747 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748}
1749
1750static size_t get_input_buffer_size(uint32_t sample_rate,
1751 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001752 int channel_count,
1753 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754{
1755 size_t size = 0;
1756
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001757 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1758 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001760 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001761 if (is_low_latency)
1762 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001763 /* ToDo: should use frame_size computed based on the format and
1764 channel_count here. */
1765 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001767 /* make sure the size is multiple of 32 bytes
1768 * At 48 kHz mono 16-bit PCM:
1769 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1770 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1771 */
1772 size += 0x1f;
1773 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001774
1775 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776}
1777
1778static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1779{
1780 struct stream_out *out = (struct stream_out *)stream;
1781
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783}
1784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001785static int out_set_sample_rate(struct audio_stream *stream __unused,
1786 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787{
1788 return -ENOSYS;
1789}
1790
1791static size_t out_get_buffer_size(const struct audio_stream *stream)
1792{
1793 struct stream_out *out = (struct stream_out *)stream;
1794
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001795 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001797 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1798 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001800 return out->config.period_size *
1801 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802}
1803
1804static uint32_t out_get_channels(const struct audio_stream *stream)
1805{
1806 struct stream_out *out = (struct stream_out *)stream;
1807
1808 return out->channel_mask;
1809}
1810
1811static audio_format_t out_get_format(const struct audio_stream *stream)
1812{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001813 struct stream_out *out = (struct stream_out *)stream;
1814
1815 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816}
1817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001818static int out_set_format(struct audio_stream *stream __unused,
1819 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820{
1821 return -ENOSYS;
1822}
1823
1824static int out_standby(struct audio_stream *stream)
1825{
1826 struct stream_out *out = (struct stream_out *)stream;
1827 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001828
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301829 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1830 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001831 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1832 /* Ignore standby in case of voip call because the voip output
1833 * stream is closed in adev_close_output_stream()
1834 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301835 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001836 return 0;
1837 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001841 if (adev->adm_deregister_stream)
1842 adev->adm_deregister_stream(adev->adm_data, out->handle);
1843
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001844 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001846 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847 if (out->pcm) {
1848 pcm_close(out->pcm);
1849 out->pcm = NULL;
1850 }
1851 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001852 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001853 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301854 out->send_next_track_params = false;
1855 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001856 out->gapless_mdata.encoder_delay = 0;
1857 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 if (out->compr != NULL) {
1859 compress_close(out->compr);
1860 out->compr = NULL;
1861 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001864 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 }
1866 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001867 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868 return 0;
1869}
1870
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001871static int out_dump(const struct audio_stream *stream __unused,
1872 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873{
1874 return 0;
1875}
1876
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001877static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1878{
1879 int ret = 0;
1880 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001881
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001882 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001883 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001884 return -EINVAL;
1885 }
1886
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301887 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001888
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001889 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1890 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301891 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001892 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001893 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1894 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301895 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001896 }
1897
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001898 ALOGV("%s new encoder delay %u and padding %u", __func__,
1899 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1900
1901 return 0;
1902}
1903
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001904static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1905{
1906 return out == adev->primary_output || out == adev->voice_tx_output;
1907}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1910{
1911 struct stream_out *out = (struct stream_out *)stream;
1912 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001913 struct audio_usecase *usecase;
1914 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 struct str_parms *parms;
1916 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001917 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001918 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919
sangwoobc677242013-08-08 16:53:43 +09001920 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001921 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301923 if (!parms)
1924 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001925 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1926 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001929 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001931 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301932 * When HDMI cable is unplugged/usb hs is disconnected the
1933 * music playback is paused and the policy manager sends routing=0
1934 * But the audioflingercontinues to write data until standby time
1935 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001936 * Avoid this by routing audio to speaker until standby.
1937 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301938 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1939 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001941 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1942 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943 }
1944
1945 /*
1946 * select_devices() call below switches all the usecases on the same
1947 * backend to the new device. Refer to check_usecases_codec_backend() in
1948 * the select_devices(). But how do we undo this?
1949 *
1950 * For example, music playback is active on headset (deep-buffer usecase)
1951 * and if we go to ringtones and select a ringtone, low-latency usecase
1952 * will be started on headset+speaker. As we can't enable headset+speaker
1953 * and headset devices at the same time, select_devices() switches the music
1954 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1955 * So when the ringtone playback is completed, how do we undo the same?
1956 *
1957 * We are relying on the out_set_parameters() call on deep-buffer output,
1958 * once the ringtone playback is ended.
1959 * NOTE: We should not check if the current devices are same as new devices.
1960 * Because select_devices() must be called to switch back the music
1961 * playback to headset.
1962 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001963 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 out->devices = val;
1965
1966 if (!out->standby)
1967 select_devices(adev, out->usecase);
1968
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001969 if (output_drives_call(adev, out)) {
1970 if(!voice_is_in_call(adev)) {
1971 if (adev->mode == AUDIO_MODE_IN_CALL) {
1972 adev->current_call_output = out;
1973 ret = voice_start_call(adev);
1974 }
1975 } else {
1976 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001977 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001978 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001979 }
1980 }
1981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001983 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001985
1986 if (out == adev->primary_output) {
1987 pthread_mutex_lock(&adev->lock);
1988 audio_extn_set_parameters(adev, parms);
1989 pthread_mutex_unlock(&adev->lock);
1990 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001991 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001992 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001993 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001994
1995 audio_extn_dts_create_state_notifier_node(out->usecase);
1996 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1997 popcount(out->channel_mask),
1998 out->playback_started);
1999
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002000 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002001 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302004error:
Eric Laurent994a6932013-07-17 11:51:42 -07002005 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 return ret;
2007}
2008
2009static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2010{
2011 struct stream_out *out = (struct stream_out *)stream;
2012 struct str_parms *query = str_parms_create_str(keys);
2013 char *str;
2014 char value[256];
2015 struct str_parms *reply = str_parms_create();
2016 size_t i, j;
2017 int ret;
2018 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002019
2020 if (!query || !reply) {
2021 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2022 return NULL;
2023 }
2024
Eric Laurent994a6932013-07-17 11:51:42 -07002025 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2027 if (ret >= 0) {
2028 value[0] = '\0';
2029 i = 0;
2030 while (out->supported_channel_masks[i] != 0) {
2031 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2032 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2033 if (!first) {
2034 strcat(value, "|");
2035 }
2036 strcat(value, out_channels_name_to_enum_table[j].name);
2037 first = false;
2038 break;
2039 }
2040 }
2041 i++;
2042 }
2043 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2044 str = str_parms_to_str(reply);
2045 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002046 voice_extn_out_get_parameters(out, query, reply);
2047 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002048 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002049 free(str);
2050 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002051 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002053
2054 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2055 if (ret >= 0) {
2056 value[0] = '\0';
2057 i = 0;
2058 first = true;
2059 while (out->supported_formats[i] != 0) {
2060 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2061 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2062 if (!first) {
2063 strcat(value, "|");
2064 }
2065 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2066 first = false;
2067 break;
2068 }
2069 }
2070 i++;
2071 }
2072 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2073 str = str_parms_to_str(reply);
2074 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 str_parms_destroy(query);
2076 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002077 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 return str;
2079}
2080
2081static uint32_t out_get_latency(const struct audio_stream_out *stream)
2082{
2083 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002084 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085
Alexy Josephaa54c872014-12-03 02:46:47 -08002086 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002087 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002088 } else {
2089 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002091 }
2092
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302093 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002094 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095}
2096
2097static int out_set_volume(struct audio_stream_out *stream, float left,
2098 float right)
2099{
Eric Laurenta9024de2013-04-04 09:19:12 -07002100 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 int volume[2];
2102
Eric Laurenta9024de2013-04-04 09:19:12 -07002103 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2104 /* only take left channel into account: the API is for stereo anyway */
2105 out->muted = (left == 0.0f);
2106 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002107 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002108 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2109 /*
2110 * Set mute or umute on HDMI passthrough stream.
2111 * Only take left channel into account.
2112 * Mute is 0 and unmute 1
2113 */
2114 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2115 } else {
2116 char mixer_ctl_name[128];
2117 struct audio_device *adev = out->dev;
2118 struct mixer_ctl *ctl;
2119 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002120 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002122 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2123 "Compress Playback %d Volume", pcm_device_id);
2124 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2125 if (!ctl) {
2126 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2127 __func__, mixer_ctl_name);
2128 return -EINVAL;
2129 }
2130 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2131 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2132 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2133 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002135 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 return -ENOSYS;
2138}
2139
2140static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2141 size_t bytes)
2142{
2143 struct stream_out *out = (struct stream_out *)stream;
2144 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302145 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002146 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302149
Naresh Tanniru80659832014-06-04 18:17:56 +05302150 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002151 // increase written size during SSR to avoid mismatch
2152 // with the written frames count in AF
2153 if (!is_offload_usecase(out->usecase))
2154 out->written += bytes / (out->config.channels * sizeof(short));
2155
Naresh Tanniru80659832014-06-04 18:17:56 +05302156 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302157 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302158 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302159 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002160 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302161 //during SSR for compress usecase we should return error to flinger
2162 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2163 pthread_mutex_unlock(&out->lock);
2164 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165 }
2166 }
2167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002169 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002170 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002171 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2172 ret = voice_extn_compress_voip_start_output_stream(out);
2173 else
2174 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002175 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002176 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002178 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 goto exit;
2180 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002181 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2182 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002185 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002186 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002187 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002188 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002189 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2190 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302191 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2192 ALOGD("copl(%p):send next track params in gapless", out);
2193 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2194 out->send_next_track_params = false;
2195 out->is_compr_metadata_avail = false;
2196 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002197 }
2198
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302200 if (ret < 0)
2201 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002202 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002203 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302204 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302206 } else if (-ENETRESET == ret) {
2207 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2208 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2209 pthread_mutex_unlock(&out->lock);
2210 out_standby(&out->stream.common);
2211 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302213 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002215 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002216 out->playback_started = 1;
2217 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002218
2219 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2220 popcount(out->channel_mask),
2221 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 }
2223 pthread_mutex_unlock(&out->lock);
2224 return ret;
2225 } else {
2226 if (out->pcm) {
2227 if (out->muted)
2228 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002229
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002231
2232 if (adev->adm_request_focus)
2233 adev->adm_request_focus(adev->adm_data, out->handle);
2234
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002235 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2236 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2237 else
2238 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002239
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302240 if (ret < 0)
2241 ret = -errno;
2242 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002243 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002244
2245 if (adev->adm_abandon_focus)
2246 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 }
2249
2250exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302251 /* ToDo: There may be a corner case when SSR happens back to back during
2252 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302253 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302254 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302255 }
2256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 pthread_mutex_unlock(&out->lock);
2258
2259 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002260 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002261 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302262 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302263 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302264 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302265 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302266 out->standby = true;
2267 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002269 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302270 out_get_sample_rate(&out->stream.common));
2271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272 }
2273 return bytes;
2274}
2275
2276static int out_get_render_position(const struct audio_stream_out *stream,
2277 uint32_t *dsp_frames)
2278{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302280 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002281
2282 if (dsp_frames == NULL)
2283 return -EINVAL;
2284
2285 *dsp_frames = 0;
2286 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002287 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 pthread_mutex_lock(&out->lock);
2289 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302290 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302292 if (ret < 0)
2293 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002294 ALOGVV("%s rendered frames %d sample_rate %d",
2295 __func__, *dsp_frames, out->sample_rate);
2296 }
2297 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302298 if (-ENETRESET == ret) {
2299 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2300 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2301 return -EINVAL;
2302 } else if(ret < 0) {
2303 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2304 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302305 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2306 /*
2307 * Handle corner case where compress session is closed during SSR
2308 * and timestamp is queried
2309 */
2310 ALOGE(" ERROR: sound card not active, return error");
2311 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302312 } else {
2313 return 0;
2314 }
Zhou Song32a556e2015-05-05 10:46:56 +08002315 } else if (audio_is_linear_pcm(out->format)) {
2316 *dsp_frames = out->written;
2317 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002318 } else
2319 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320}
2321
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002322static int out_add_audio_effect(const struct audio_stream *stream __unused,
2323 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324{
2325 return 0;
2326}
2327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002328static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2329 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330{
2331 return 0;
2332}
2333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002334static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2335 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336{
2337 return -EINVAL;
2338}
2339
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002340static int out_get_presentation_position(const struct audio_stream_out *stream,
2341 uint64_t *frames, struct timespec *timestamp)
2342{
2343 struct stream_out *out = (struct stream_out *)stream;
2344 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002345 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002346
2347 pthread_mutex_lock(&out->lock);
2348
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002349 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002350 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302351 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002352 &out->sample_rate);
2353 ALOGVV("%s rendered frames %ld sample_rate %d",
2354 __func__, dsp_frames, out->sample_rate);
2355 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302356 if (ret < 0)
2357 ret = -errno;
2358 if (-ENETRESET == ret) {
2359 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2360 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2361 ret = -EINVAL;
2362 } else
2363 ret = 0;
2364
Eric Laurent949a0892013-09-20 09:20:13 -07002365 /* this is the best we can do */
2366 clock_gettime(CLOCK_MONOTONIC, timestamp);
2367 }
2368 } else {
2369 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002370 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002371 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2372 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002373 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002374 // This adjustment accounts for buffering after app processor.
2375 // It is based on estimated DSP latency per use case, rather than exact.
2376 signed_frames -=
2377 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2378
Eric Laurent949a0892013-09-20 09:20:13 -07002379 // It would be unusual for this value to be negative, but check just in case ...
2380 if (signed_frames >= 0) {
2381 *frames = signed_frames;
2382 ret = 0;
2383 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002384 }
2385 }
2386 }
2387
2388 pthread_mutex_unlock(&out->lock);
2389
2390 return ret;
2391}
2392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393static int out_set_callback(struct audio_stream_out *stream,
2394 stream_callback_t callback, void *cookie)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397
2398 ALOGV("%s", __func__);
2399 pthread_mutex_lock(&out->lock);
2400 out->offload_callback = callback;
2401 out->offload_cookie = cookie;
2402 pthread_mutex_unlock(&out->lock);
2403 return 0;
2404}
2405
2406static int out_pause(struct audio_stream_out* stream)
2407{
2408 struct stream_out *out = (struct stream_out *)stream;
2409 int status = -ENOSYS;
2410 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002411 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002412 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 pthread_mutex_lock(&out->lock);
2414 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302415 struct audio_device *adev = out->dev;
2416 int snd_scard_state = get_snd_card_state(adev);
2417
2418 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2419 status = compress_pause(out->compr);
2420
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002421 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002422
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302423 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002424 audio_extn_dts_notify_playback_state(out->usecase, 0,
2425 out->sample_rate, popcount(out->channel_mask),
2426 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 }
2428 pthread_mutex_unlock(&out->lock);
2429 }
2430 return status;
2431}
2432
2433static int out_resume(struct audio_stream_out* stream)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 int status = -ENOSYS;
2437 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002438 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002439 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 status = 0;
2441 pthread_mutex_lock(&out->lock);
2442 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302443 struct audio_device *adev = out->dev;
2444 int snd_scard_state = get_snd_card_state(adev);
2445
2446 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2447 status = compress_resume(out->compr);
2448
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002450
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302451 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002452 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2453 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 }
2455 pthread_mutex_unlock(&out->lock);
2456 }
2457 return status;
2458}
2459
2460static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2461{
2462 struct stream_out *out = (struct stream_out *)stream;
2463 int status = -ENOSYS;
2464 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002465 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 pthread_mutex_lock(&out->lock);
2467 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2468 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2469 else
2470 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2471 pthread_mutex_unlock(&out->lock);
2472 }
2473 return status;
2474}
2475
2476static int out_flush(struct audio_stream_out* stream)
2477{
2478 struct stream_out *out = (struct stream_out *)stream;
2479 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002480 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002481 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482 pthread_mutex_lock(&out->lock);
2483 stop_compressed_output_l(out);
2484 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002485 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486 return 0;
2487 }
2488 return -ENOSYS;
2489}
2490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491/** audio_stream_in implementation **/
2492static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2493{
2494 struct stream_in *in = (struct stream_in *)stream;
2495
2496 return in->config.rate;
2497}
2498
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002499static int in_set_sample_rate(struct audio_stream *stream __unused,
2500 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501{
2502 return -ENOSYS;
2503}
2504
2505static size_t in_get_buffer_size(const struct audio_stream *stream)
2506{
2507 struct stream_in *in = (struct stream_in *)stream;
2508
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002509 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2510 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002511 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2512 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002513
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002514 return in->config.period_size *
2515 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516}
2517
2518static uint32_t in_get_channels(const struct audio_stream *stream)
2519{
2520 struct stream_in *in = (struct stream_in *)stream;
2521
2522 return in->channel_mask;
2523}
2524
2525static audio_format_t in_get_format(const struct audio_stream *stream)
2526{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002527 struct stream_in *in = (struct stream_in *)stream;
2528
2529 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530}
2531
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002532static int in_set_format(struct audio_stream *stream __unused,
2533 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534{
2535 return -ENOSYS;
2536}
2537
2538static int in_standby(struct audio_stream *stream)
2539{
2540 struct stream_in *in = (struct stream_in *)stream;
2541 struct audio_device *adev = in->dev;
2542 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302543 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2544 stream, in->usecase, use_case_table[in->usecase]);
2545
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002546 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2547 /* Ignore standby in case of voip call because the voip input
2548 * stream is closed in adev_close_input_stream()
2549 */
2550 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2551 return status;
2552 }
2553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002555 if (!in->standby && in->is_st_session) {
2556 ALOGD("%s: sound trigger pcm stop lab", __func__);
2557 audio_extn_sound_trigger_stop_lab(in);
2558 in->standby = 1;
2559 }
2560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002562 if (adev->adm_deregister_stream)
2563 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2564
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002565 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002567 if (in->pcm) {
2568 pcm_close(in->pcm);
2569 in->pcm = NULL;
2570 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002572 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 }
2574 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002575 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 return status;
2577}
2578
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002579static int in_dump(const struct audio_stream *stream __unused,
2580 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581{
2582 return 0;
2583}
2584
2585static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2586{
2587 struct stream_in *in = (struct stream_in *)stream;
2588 struct audio_device *adev = in->dev;
2589 struct str_parms *parms;
2590 char *str;
2591 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002592 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302594 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 parms = str_parms_create_str(kvpairs);
2596
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302597 if (!parms)
2598 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002600 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002601
2602 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2603 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 val = atoi(value);
2605 /* no audio source uses val == 0 */
2606 if ((in->source != val) && (val != 0)) {
2607 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002608 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2609 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2610 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2611 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002612 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002613 err = voice_extn_compress_voip_open_input_stream(in);
2614 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002615 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002616 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002617 }
2618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 }
2620 }
2621
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002622 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2623 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002625 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 in->device = val;
2627 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002628 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002629 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 }
2631 }
2632
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002633done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002635 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
2637 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302638error:
Eric Laurent994a6932013-07-17 11:51:42 -07002639 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 return ret;
2641}
2642
2643static char* in_get_parameters(const struct audio_stream *stream,
2644 const char *keys)
2645{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002646 struct stream_in *in = (struct stream_in *)stream;
2647 struct str_parms *query = str_parms_create_str(keys);
2648 char *str;
2649 char value[256];
2650 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002651
2652 if (!query || !reply) {
2653 ALOGE("in_get_parameters: failed to create query or reply");
2654 return NULL;
2655 }
2656
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002657 ALOGV("%s: enter: keys - %s", __func__, keys);
2658
2659 voice_extn_in_get_parameters(in, query, reply);
2660
2661 str = str_parms_to_str(reply);
2662 str_parms_destroy(query);
2663 str_parms_destroy(reply);
2664
2665 ALOGV("%s: exit: returns - %s", __func__, str);
2666 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667}
2668
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002669static int in_set_gain(struct audio_stream_in *stream __unused,
2670 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671{
2672 return 0;
2673}
2674
2675static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2676 size_t bytes)
2677{
2678 struct stream_in *in = (struct stream_in *)stream;
2679 struct audio_device *adev = in->dev;
2680 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302681 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302684
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002685 if (in->is_st_session) {
2686 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2687 /* Read from sound trigger HAL */
2688 audio_extn_sound_trigger_read(in, buffer, bytes);
2689 pthread_mutex_unlock(&in->lock);
2690 return bytes;
2691 }
2692
2693 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2694 ALOGD(" %s: sound card is not active/SSR state", __func__);
2695 ret= -EIO;;
2696 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302697 }
2698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002700 pthread_mutex_lock(&adev->lock);
2701 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2702 ret = voice_extn_compress_voip_start_input_stream(in);
2703 else
2704 ret = start_input_stream(in);
2705 pthread_mutex_unlock(&adev->lock);
2706 if (ret != 0) {
2707 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 }
2709 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002710 if (adev->adm_register_input_stream)
2711 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002714 if (adev->adm_request_focus)
2715 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002718 if (audio_extn_ssr_get_enabled() &&
2719 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002720 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002721 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2722 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002723 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2724 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002725 else
2726 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302727 if (ret < 0)
2728 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 }
2730
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002731 if (adev->adm_abandon_focus)
2732 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 /*
2735 * Instead of writing zeroes here, we could trust the hardware
2736 * to always provide zeroes when muted.
2737 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302738 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2739 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 memset(buffer, 0, bytes);
2741
2742exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302743 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302744 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002745 if (-ENETRESET == ret)
2746 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 pthread_mutex_unlock(&in->lock);
2749
2750 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302751 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302752 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302753 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302754 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302755 in->standby = true;
2756 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302757 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002759 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002760 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302761 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 }
2763 return bytes;
2764}
2765
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002766static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767{
2768 return 0;
2769}
2770
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002771static int add_remove_audio_effect(const struct audio_stream *stream,
2772 effect_handle_t effect,
2773 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002775 struct stream_in *in = (struct stream_in *)stream;
2776 int status = 0;
2777 effect_descriptor_t desc;
2778
2779 status = (*effect)->get_descriptor(effect, &desc);
2780 if (status != 0)
2781 return status;
2782
2783 pthread_mutex_lock(&in->lock);
2784 pthread_mutex_lock(&in->dev->lock);
2785 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2786 in->enable_aec != enable &&
2787 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2788 in->enable_aec = enable;
2789 if (!in->standby)
2790 select_devices(in->dev, in->usecase);
2791 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002792 if (in->enable_ns != enable &&
2793 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2794 in->enable_ns = enable;
2795 if (!in->standby)
2796 select_devices(in->dev, in->usecase);
2797 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002798 pthread_mutex_unlock(&in->dev->lock);
2799 pthread_mutex_unlock(&in->lock);
2800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 return 0;
2802}
2803
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002804static int in_add_audio_effect(const struct audio_stream *stream,
2805 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806{
Eric Laurent994a6932013-07-17 11:51:42 -07002807 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002808 return add_remove_audio_effect(stream, effect, true);
2809}
2810
2811static int in_remove_audio_effect(const struct audio_stream *stream,
2812 effect_handle_t effect)
2813{
Eric Laurent994a6932013-07-17 11:51:42 -07002814 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002815 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816}
2817
2818static int adev_open_output_stream(struct audio_hw_device *dev,
2819 audio_io_handle_t handle,
2820 audio_devices_t devices,
2821 audio_output_flags_t flags,
2822 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002823 struct audio_stream_out **stream_out,
2824 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825{
2826 struct audio_device *adev = (struct audio_device *)dev;
2827 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002828 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002829 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302832
2833 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2834 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002835 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302836 return -EINVAL;
2837 }
2838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2840
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302841 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2842 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2843 devices, flags, &out->stream);
2844
2845
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002846 if (!out) {
2847 return -ENOMEM;
2848 }
2849
Haynes Mathew George204045b2015-02-25 20:32:03 -08002850 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2851 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 if (devices == AUDIO_DEVICE_NONE)
2854 devices = AUDIO_DEVICE_OUT_SPEAKER;
2855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 out->flags = flags;
2857 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002858 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002859 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 out->sample_rate = config->sample_rate;
2861 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2862 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002863 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002864 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002865 out->non_blocking = 0;
2866 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867
2868 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002869 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2870 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002871 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2872 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2873
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002874 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002875 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2876 ret = read_hdmi_channel_masks(out);
2877
2878 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2879 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002880 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002881 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002882 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002883
2884 if (config->sample_rate == 0)
2885 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2886 if (config->channel_mask == 0)
2887 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2888
2889 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2892 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002894 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002896 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2897 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002898 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002899 ret = voice_extn_compress_voip_open_output_stream(out);
2900 if (ret != 0) {
2901 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2902 __func__, ret);
2903 goto error_open;
2904 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002905 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2906 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2909 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2910 ALOGE("%s: Unsupported Offload information", __func__);
2911 ret = -EINVAL;
2912 goto error_open;
2913 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002914
2915 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2916 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2917 ALOGV("read and update_pass through formats");
2918 ret = audio_extn_dolby_update_passt_formats(adev, out);
2919 if(ret != 0) {
2920 goto error_open;
2921 }
2922 if(config->offload_info.format == 0)
2923 config->offload_info.format = out->supported_formats[0];
2924 }
2925
Mingming Yin90310102013-11-13 16:57:00 -08002926 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002927 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002928 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 ret = -EINVAL;
2930 goto error_open;
2931 }
2932
2933 out->compr_config.codec = (struct snd_codec *)
2934 calloc(1, sizeof(struct snd_codec));
2935
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002936 if (!out->compr_config.codec) {
2937 ret = -ENOMEM;
2938 goto error_open;
2939 }
2940
vivek mehta0ea887a2015-08-26 14:01:20 -07002941 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2942 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2943 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2944 } else {
2945 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2946 out->usecase = get_offload_usecase(adev);
2947 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002948 if (config->offload_info.channel_mask)
2949 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002950 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002952 config->offload_info.channel_mask = config->channel_mask;
2953 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002954 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 out->sample_rate = config->offload_info.sample_rate;
2956
2957 out->stream.set_callback = out_set_callback;
2958 out->stream.pause = out_pause;
2959 out->stream.resume = out_resume;
2960 out->stream.drain = out_drain;
2961 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002962 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002964 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002965 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002966 audio_extn_dolby_get_snd_codec_id(adev, out,
2967 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002968 else
2969 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002971
2972 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2973 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002974 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002975 platform_get_pcm_offload_buffer_size(&config->offload_info);
2976 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2977 out->compr_config.fragment_size =
2978 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002979 } else {
2980 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002981 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002982 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2984 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002985 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986 out->compr_config.codec->bit_rate =
2987 config->offload_info.bit_rate;
2988 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002989 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002990 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302991 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002992 /*TODO: Do we need to change it for passthrough */
2993 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994
Manish Dewangana6fc5442015-08-24 20:30:31 +05302995 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2996 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2997 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2998 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002999 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3000 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003001 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003002 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003003 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3004 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003005
Mingming Yin3ee55c62014-08-04 14:23:35 -07003006 if (out->bit_width == 24) {
3007 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3008 }
3009
Amit Shekhar6f461b12014-08-01 14:52:58 -07003010 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303011 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003012
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003013 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3014 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003015
Mingming Yin497419f2015-07-01 16:57:32 -07003016 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003017 //this flag is set from framework only if its for PCM formats
3018 //no need to check for PCM format again
3019 out->non_blocking = 0;
3020 out->use_small_bufs = true;
3021 ALOGI("Keep write blocking for small buff: non_blockling %d",
3022 out->non_blocking);
3023 }
3024
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003025 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303026 out->send_next_track_params = false;
3027 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003028 out->offload_state = OFFLOAD_STATE_IDLE;
3029 out->playback_started = 0;
3030
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003031 audio_extn_dts_create_state_notifier_node(out->usecase);
3032
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 create_offload_callback_thread(out);
3034 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3035 __func__, config->offload_info.version,
3036 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003037 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003038 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003039 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3040 ret = voice_check_and_set_incall_music_usecase(adev, out);
3041 if (ret != 0) {
3042 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3043 __func__, ret);
3044 goto error_open;
3045 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003046 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3047 if (config->sample_rate == 0)
3048 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3049 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3050 config->sample_rate != 8000) {
3051 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3052 ret = -EINVAL;
3053 goto error_open;
3054 }
3055 out->sample_rate = config->sample_rate;
3056 out->config.rate = config->sample_rate;
3057 if (config->format == AUDIO_FORMAT_DEFAULT)
3058 config->format = AUDIO_FORMAT_PCM_16_BIT;
3059 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3060 config->format = AUDIO_FORMAT_PCM_16_BIT;
3061 ret = -EINVAL;
3062 goto error_open;
3063 }
3064 out->format = config->format;
3065 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3066 out->config = pcm_config_afe_proxy_playback;
3067 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003068 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3069 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3070 out->config = pcm_config_low_latency;
3071 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003072 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003073 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3075 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003076 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003077 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3078 format = AUDIO_FORMAT_PCM_16_BIT;
3079 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3080 out->config = pcm_config_deep_buffer;
3081 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003082 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003083 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003084 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003085 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003086 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003087 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 }
3089
Amit Shekhar1d896042014-10-03 13:16:09 -07003090 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3091 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003092 /* TODO remove this hardcoding and check why width is zero*/
3093 if (out->bit_width == 0)
3094 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003095 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3096 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003097 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003098 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003099 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3100 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3101 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003102 if(adev->primary_output == NULL)
3103 adev->primary_output = out;
3104 else {
3105 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003106 ret = -EEXIST;
3107 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003108 }
3109 }
3110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 /* Check if this usecase is already existing */
3112 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003113 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3114 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003117 ret = -EEXIST;
3118 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 }
3120 pthread_mutex_unlock(&adev->lock);
3121
3122 out->stream.common.get_sample_rate = out_get_sample_rate;
3123 out->stream.common.set_sample_rate = out_set_sample_rate;
3124 out->stream.common.get_buffer_size = out_get_buffer_size;
3125 out->stream.common.get_channels = out_get_channels;
3126 out->stream.common.get_format = out_get_format;
3127 out->stream.common.set_format = out_set_format;
3128 out->stream.common.standby = out_standby;
3129 out->stream.common.dump = out_dump;
3130 out->stream.common.set_parameters = out_set_parameters;
3131 out->stream.common.get_parameters = out_get_parameters;
3132 out->stream.common.add_audio_effect = out_add_audio_effect;
3133 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3134 out->stream.get_latency = out_get_latency;
3135 out->stream.set_volume = out_set_volume;
3136 out->stream.write = out_write;
3137 out->stream.get_render_position = out_get_render_position;
3138 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003139 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003142 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003143 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144
3145 config->format = out->stream.common.get_format(&out->stream.common);
3146 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3147 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3148
3149 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303150 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003151 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003152
3153 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3154 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3155 popcount(out->channel_mask), out->playback_started);
3156
Eric Laurent994a6932013-07-17 11:51:42 -07003157 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003159
3160error_open:
3161 free(out);
3162 *stream_out = NULL;
3163 ALOGD("%s: exit: ret %d", __func__, ret);
3164 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165}
3166
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003167static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 struct audio_stream_out *stream)
3169{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 struct stream_out *out = (struct stream_out *)stream;
3171 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003172 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003173
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303174 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3175
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003176 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303177 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003178 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303179 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003180 if(ret != 0)
3181 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3182 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003183 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003184 out_standby(&stream->common);
3185
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003186 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003187 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003188 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003189 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 if (out->compr_config.codec != NULL)
3191 free(out->compr_config.codec);
3192 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003193
3194 if (adev->voice_tx_output == out)
3195 adev->voice_tx_output = NULL;
3196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 pthread_cond_destroy(&out->cond);
3198 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003200 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201}
3202
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003203static void close_compress_sessions(struct audio_device *adev)
3204{
Mingming Yin7b762e72015-03-04 13:47:32 -08003205 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303206 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003207 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003208 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303209
3210 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003211 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303212 if (is_offload_usecase(usecase->id)) {
3213 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003214 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3215 out = usecase->stream.out;
3216 pthread_mutex_unlock(&adev->lock);
3217 out_standby(&out->stream.common);
3218 pthread_mutex_lock(&adev->lock);
3219 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303220 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003221 }
3222 pthread_mutex_unlock(&adev->lock);
3223}
3224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3226{
3227 struct audio_device *adev = (struct audio_device *)dev;
3228 struct str_parms *parms;
3229 char *str;
3230 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003231 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003232 int ret;
3233 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003235 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303238 if (!parms)
3239 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003240 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3241 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303242 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303243 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303244 struct listnode *node;
3245 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303246 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303247 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003248 //close compress sessions on OFFLINE status
3249 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303250 } else if (strstr(snd_card_status, "ONLINE")) {
3251 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303252 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003253 //send dts hpx license if enabled
3254 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303255 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303256 }
3257
3258 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003259 status = voice_set_parameters(adev, parms);
3260 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003261 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003263 status = platform_set_parameters(adev->platform, parms);
3264 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003265 goto done;
3266
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003267 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3268 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003269 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3271 adev->bluetooth_nrec = true;
3272 else
3273 adev->bluetooth_nrec = false;
3274 }
3275
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003276 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3277 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3279 adev->screen_off = false;
3280 else
3281 adev->screen_off = true;
3282 }
3283
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003284 ret = str_parms_get_int(parms, "rotation", &val);
3285 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003286 bool reverse_speakers = false;
3287 switch(val) {
3288 // FIXME: note that the code below assumes that the speakers are in the correct placement
3289 // relative to the user when the device is rotated 90deg from its default rotation. This
3290 // assumption is device-specific, not platform-specific like this code.
3291 case 270:
3292 reverse_speakers = true;
3293 break;
3294 case 0:
3295 case 90:
3296 case 180:
3297 break;
3298 default:
3299 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003300 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003301 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003302 if (status == 0) {
3303 if (adev->speaker_lr_swap != reverse_speakers) {
3304 adev->speaker_lr_swap = reverse_speakers;
3305 // only update the selected device if there is active pcm playback
3306 struct audio_usecase *usecase;
3307 struct listnode *node;
3308 list_for_each(node, &adev->usecase_list) {
3309 usecase = node_to_item(node, struct audio_usecase, list);
3310 if (usecase->type == PCM_PLAYBACK) {
3311 select_devices(adev, usecase->id);
3312 break;
3313 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003314 }
3315 }
3316 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003317 }
3318
Mingming Yin514a8bc2014-07-29 15:22:21 -07003319 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3320 if (ret >= 0) {
3321 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3322 adev->bt_wb_speech_enabled = true;
3323 else
3324 adev->bt_wb_speech_enabled = false;
3325 }
3326
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003327 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3328 if (ret >= 0) {
3329 val = atoi(value);
3330 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3331 ALOGV("cache new edid");
3332 platform_cache_edid(adev->platform);
3333 }
3334 }
3335
3336 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3337 if (ret >= 0) {
3338 val = atoi(value);
3339 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3340 ALOGV("invalidate cached edid");
3341 platform_invalidate_edid(adev->platform);
3342 }
3343 }
3344
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003345 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003346
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003347done:
3348 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003349 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303350error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003351 ALOGV("%s: exit with code(%d)", __func__, status);
3352 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353}
3354
3355static char* adev_get_parameters(const struct audio_hw_device *dev,
3356 const char *keys)
3357{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003358 struct audio_device *adev = (struct audio_device *)dev;
3359 struct str_parms *reply = str_parms_create();
3360 struct str_parms *query = str_parms_create_str(keys);
3361 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303362 char value[256] = {0};
3363 int ret = 0;
3364
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003365 if (!query || !reply) {
3366 ALOGE("adev_get_parameters: failed to create query or reply");
3367 return NULL;
3368 }
3369
Naresh Tannirud7205b62014-06-20 02:54:48 +05303370 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3371 sizeof(value));
3372 if (ret >=0) {
3373 int val = 1;
3374 pthread_mutex_lock(&adev->snd_card_status.lock);
3375 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3376 val = 0;
3377 pthread_mutex_unlock(&adev->snd_card_status.lock);
3378 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3379 goto exit;
3380 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003381
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003382 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003383 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003384 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003385 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303386 pthread_mutex_unlock(&adev->lock);
3387
Naresh Tannirud7205b62014-06-20 02:54:48 +05303388exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003389 str = str_parms_to_str(reply);
3390 str_parms_destroy(query);
3391 str_parms_destroy(reply);
3392
3393 ALOGV("%s: exit: returns - %s", __func__, str);
3394 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395}
3396
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003397static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398{
3399 return 0;
3400}
3401
3402static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3403{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003404 int ret;
3405 struct audio_device *adev = (struct audio_device *)dev;
3406 pthread_mutex_lock(&adev->lock);
3407 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003408 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003409 pthread_mutex_unlock(&adev->lock);
3410 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411}
3412
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003413static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3414 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415{
3416 return -ENOSYS;
3417}
3418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003419static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3420 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421{
3422 return -ENOSYS;
3423}
3424
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003425static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3426 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427{
3428 return -ENOSYS;
3429}
3430
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003431static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3432 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433{
3434 return -ENOSYS;
3435}
3436
3437static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3438{
3439 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 pthread_mutex_lock(&adev->lock);
3442 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003443 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003445 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3446 voice_is_in_call(adev)) {
3447 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003448 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003449 adev->current_call_output = NULL;
3450 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451 }
3452 pthread_mutex_unlock(&adev->lock);
3453 return 0;
3454}
3455
3456static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3457{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003458 int ret;
3459
3460 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003461 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003462 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3463 pthread_mutex_unlock(&adev->lock);
3464
3465 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466}
3467
3468static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3469{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003470 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 return 0;
3472}
3473
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003474static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 const struct audio_config *config)
3476{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003477 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003479 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3480 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481}
3482
3483static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003484 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 audio_devices_t devices,
3486 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003487 struct audio_stream_in **stream_in,
3488 audio_input_flags_t flags __unused,
3489 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003490 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
3492 struct audio_device *adev = (struct audio_device *)dev;
3493 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003494 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003495 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003496 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003498 *stream_in = NULL;
3499 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3500 return -EINVAL;
3501
3502 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003503
3504 if (!in) {
3505 ALOGE("failed to allocate input stream");
3506 return -ENOMEM;
3507 }
3508
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303509 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003510 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3511 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003513 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 in->stream.common.get_sample_rate = in_get_sample_rate;
3516 in->stream.common.set_sample_rate = in_set_sample_rate;
3517 in->stream.common.get_buffer_size = in_get_buffer_size;
3518 in->stream.common.get_channels = in_get_channels;
3519 in->stream.common.get_format = in_get_format;
3520 in->stream.common.set_format = in_set_format;
3521 in->stream.common.standby = in_standby;
3522 in->stream.common.dump = in_dump;
3523 in->stream.common.set_parameters = in_set_parameters;
3524 in->stream.common.get_parameters = in_get_parameters;
3525 in->stream.common.add_audio_effect = in_add_audio_effect;
3526 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3527 in->stream.set_gain = in_set_gain;
3528 in->stream.read = in_read;
3529 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3530
3531 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003532 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 in->standby = 1;
3535 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003536 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003537 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
3539 /* Update config params with the requested sample rate and channels */
3540 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003541 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3542 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3543 is_low_latency = true;
3544#if LOW_LATENCY_CAPTURE_USE_CASE
3545 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3546#endif
3547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003550 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003552 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303553 if (adev->mode != AUDIO_MODE_IN_CALL) {
3554 ret = -EINVAL;
3555 goto err_open;
3556 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003557 if (config->sample_rate == 0)
3558 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3559 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3560 config->sample_rate != 8000) {
3561 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3562 ret = -EINVAL;
3563 goto err_open;
3564 }
3565 if (config->format == AUDIO_FORMAT_DEFAULT)
3566 config->format = AUDIO_FORMAT_PCM_16_BIT;
3567 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3568 config->format = AUDIO_FORMAT_PCM_16_BIT;
3569 ret = -EINVAL;
3570 goto err_open;
3571 }
3572
3573 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3574 in->config = pcm_config_afe_proxy_record;
3575 in->config.channels = channel_count;
3576 in->config.rate = config->sample_rate;
3577 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003578 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003579 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003580 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3581 ret = -EINVAL;
3582 goto err_open;
3583 }
3584 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003585 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003586 }
Mingming Yine62d7842013-10-25 16:26:03 -07003587 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003588 audio_extn_compr_cap_format_supported(config->format) &&
3589 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003590 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003591 } else {
3592 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003593 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003594 buffer_size = get_input_buffer_size(config->sample_rate,
3595 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003596 channel_count,
3597 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003598 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003599 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3600 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3601 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3602 (in->config.rate == 8000 || in->config.rate == 16000) &&
3603 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3604 voice_extn_compress_voip_open_input_stream(in);
3605 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003606 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003608 /* This stream could be for sound trigger lab,
3609 get sound trigger pcm if present */
3610 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303611 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003614 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003615 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616
3617err_open:
3618 free(in);
3619 *stream_in = NULL;
3620 return ret;
3621}
3622
3623static void adev_close_input_stream(struct audio_hw_device *dev,
3624 struct audio_stream_in *stream)
3625{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003626 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003627 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003628 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303629
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303630 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003631
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303632 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003633 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303634
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003635 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303636 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003637 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303638 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003639 if (ret != 0)
3640 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3641 __func__, ret);
3642 } else
3643 in_standby(&stream->common);
3644
Mingming Yin7b762e72015-03-04 13:47:32 -08003645 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003646 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003647 audio_extn_ssr_deinit();
3648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649
Mingming Yine62d7842013-10-25 16:26:03 -07003650 if(audio_extn_compr_cap_enabled() &&
3651 audio_extn_compr_cap_format_supported(in->config.format))
3652 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003653
3654 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 return;
3656}
3657
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003658static int adev_dump(const audio_hw_device_t *device __unused,
3659 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660{
3661 return 0;
3662}
3663
3664static int adev_close(hw_device_t *device)
3665{
3666 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003667
3668 if (!adev)
3669 return 0;
3670
3671 pthread_mutex_lock(&adev_init_lock);
3672
3673 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003674 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003675 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003676 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003677 audio_route_free(adev->audio_route);
3678 free(adev->snd_dev_ref_cnt);
3679 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003680 if (adev->adm_deinit)
3681 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003682 free(device);
3683 adev = NULL;
3684 }
3685 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 return 0;
3688}
3689
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003690/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3691 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3692 * just that it _might_ work.
3693 */
3694static int period_size_is_plausible_for_low_latency(int period_size)
3695{
3696 switch (period_size) {
3697 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003698 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003699 case 240:
3700 case 320:
3701 case 480:
3702 return 1;
3703 default:
3704 return 0;
3705 }
3706}
3707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708static int adev_open(const hw_module_t *module, const char *name,
3709 hw_device_t **device)
3710{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003711 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003713 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3715
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003716 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003717 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003718 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003719 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003720 ALOGD("%s: returning existing instance of adev", __func__);
3721 ALOGD("%s: exit", __func__);
3722 pthread_mutex_unlock(&adev_init_lock);
3723 return 0;
3724 }
3725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 adev = calloc(1, sizeof(struct audio_device));
3727
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003728 if (!adev) {
3729 pthread_mutex_unlock(&adev_init_lock);
3730 return -ENOMEM;
3731 }
3732
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003733 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3736 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3737 adev->device.common.module = (struct hw_module_t *)module;
3738 adev->device.common.close = adev_close;
3739
3740 adev->device.init_check = adev_init_check;
3741 adev->device.set_voice_volume = adev_set_voice_volume;
3742 adev->device.set_master_volume = adev_set_master_volume;
3743 adev->device.get_master_volume = adev_get_master_volume;
3744 adev->device.set_master_mute = adev_set_master_mute;
3745 adev->device.get_master_mute = adev_get_master_mute;
3746 adev->device.set_mode = adev_set_mode;
3747 adev->device.set_mic_mute = adev_set_mic_mute;
3748 adev->device.get_mic_mute = adev_get_mic_mute;
3749 adev->device.set_parameters = adev_set_parameters;
3750 adev->device.get_parameters = adev_get_parameters;
3751 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3752 adev->device.open_output_stream = adev_open_output_stream;
3753 adev->device.close_output_stream = adev_close_output_stream;
3754 adev->device.open_input_stream = adev_open_input_stream;
3755 adev->device.close_input_stream = adev_close_input_stream;
3756 adev->device.dump = adev_dump;
3757
3758 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003760 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003761 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003764 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003765 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003766 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003767 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003768 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003769 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003770 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303771
3772 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3773 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003775 adev->platform = platform_init(adev);
3776 if (!adev->platform) {
3777 free(adev->snd_dev_ref_cnt);
3778 free(adev);
3779 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3780 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003781 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003782 return -EINVAL;
3783 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003784
Naresh Tanniru4c630392014-05-12 01:05:52 +05303785 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3786
Eric Laurentc4aef752013-09-12 17:45:53 -07003787 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3788 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3789 if (adev->visualizer_lib == NULL) {
3790 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3791 } else {
3792 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3793 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003794 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003795 "visualizer_hal_start_output");
3796 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003797 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003798 "visualizer_hal_stop_output");
3799 }
3800 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003801 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003802 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003803
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003804 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3805 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3806 if (adev->offload_effects_lib == NULL) {
3807 ALOGE("%s: DLOPEN failed for %s", __func__,
3808 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3809 } else {
3810 ALOGV("%s: DLOPEN successful for %s", __func__,
3811 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3812 adev->offload_effects_start_output =
3813 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3814 "offload_effects_bundle_hal_start_output");
3815 adev->offload_effects_stop_output =
3816 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3817 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003818 adev->offload_effects_set_hpx_state =
3819 (int (*)(bool))dlsym(adev->offload_effects_lib,
3820 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303821 adev->offload_effects_get_parameters =
3822 (void (*)(struct str_parms *, struct str_parms *))
3823 dlsym(adev->offload_effects_lib,
3824 "offload_effects_bundle_get_parameters");
3825 adev->offload_effects_set_parameters =
3826 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3827 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003828 }
3829 }
3830
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003831 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3832 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3833 if (adev->adm_lib == NULL) {
3834 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3835 } else {
3836 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3837 adev->adm_init = (adm_init_t)
3838 dlsym(adev->adm_lib, "adm_init");
3839 adev->adm_deinit = (adm_deinit_t)
3840 dlsym(adev->adm_lib, "adm_deinit");
3841 adev->adm_register_input_stream = (adm_register_input_stream_t)
3842 dlsym(adev->adm_lib, "adm_register_input_stream");
3843 adev->adm_register_output_stream = (adm_register_output_stream_t)
3844 dlsym(adev->adm_lib, "adm_register_output_stream");
3845 adev->adm_deregister_stream = (adm_deregister_stream_t)
3846 dlsym(adev->adm_lib, "adm_deregister_stream");
3847 adev->adm_request_focus = (adm_request_focus_t)
3848 dlsym(adev->adm_lib, "adm_request_focus");
3849 adev->adm_abandon_focus = (adm_abandon_focus_t)
3850 dlsym(adev->adm_lib, "adm_abandon_focus");
3851 }
3852 }
3853
Mingming Yin514a8bc2014-07-29 15:22:21 -07003854 adev->bt_wb_speech_enabled = false;
3855
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003856 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 *device = &adev->device.common;
3858
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003859 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3860 &adev->streams_output_cfg_list);
3861
Kiran Kandi910e1862013-10-29 13:29:42 -07003862 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003863
3864 char value[PROPERTY_VALUE_MAX];
3865 int trial;
3866 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3867 trial = atoi(value);
3868 if (period_size_is_plausible_for_low_latency(trial)) {
3869 pcm_config_low_latency.period_size = trial;
3870 pcm_config_low_latency.start_threshold = trial / 4;
3871 pcm_config_low_latency.avail_min = trial / 4;
3872 configured_low_latency_capture_period_size = trial;
3873 }
3874 }
3875 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3876 trial = atoi(value);
3877 if (period_size_is_plausible_for_low_latency(trial)) {
3878 configured_low_latency_capture_period_size = trial;
3879 }
3880 }
3881
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003882 pthread_mutex_unlock(&adev_init_lock);
3883
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003884 if (adev->adm_init)
3885 adev->adm_data = adev->adm_init();
3886
Eric Laurent994a6932013-07-17 11:51:42 -07003887 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 return 0;
3889}
3890
3891static struct hw_module_methods_t hal_module_methods = {
3892 .open = adev_open,
3893};
3894
3895struct audio_module HAL_MODULE_INFO_SYM = {
3896 .common = {
3897 .tag = HARDWARE_MODULE_TAG,
3898 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3899 .hal_api_version = HARDWARE_HAL_API_VERSION,
3900 .id = AUDIO_HARDWARE_MODULE_ID,
3901 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003902 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 .methods = &hal_module_methods,
3904 },
3905};