blob: e35f26d5b98d90fc92f5f0ea97db3a2ad79b6344 [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);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700457 audio_extn_utils_send_app_type_cfg(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;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001177 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001178
1179 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001180}
1181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001182/* must be called with out->lock locked */
1183static int send_offload_cmd_l(struct stream_out* out, int command)
1184{
1185 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1186
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001187 if (!cmd) {
1188 ALOGE("failed to allocate mem for command 0x%x", command);
1189 return -ENOMEM;
1190 }
1191
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001192 ALOGVV("%s %d", __func__, command);
1193
1194 cmd->cmd = command;
1195 list_add_tail(&out->offload_cmd_list, &cmd->node);
1196 pthread_cond_signal(&out->offload_cond);
1197 return 0;
1198}
1199
1200/* must be called iwth out->lock locked */
1201static void stop_compressed_output_l(struct stream_out *out)
1202{
1203 out->offload_state = OFFLOAD_STATE_IDLE;
1204 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001205 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001206 if (out->compr != NULL) {
1207 compress_stop(out->compr);
1208 while (out->offload_thread_blocked) {
1209 pthread_cond_wait(&out->cond, &out->lock);
1210 }
1211 }
1212}
1213
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001214bool is_offload_usecase(audio_usecase_t uc_id)
1215{
1216 unsigned int i;
1217 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1218 if (uc_id == offload_usecases[i])
1219 return true;
1220 }
1221 return false;
1222}
1223
1224static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1225{
1226 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1227 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1228 char value[PROPERTY_VALUE_MAX] = {0};
1229
1230 property_get("audio.offload.multiple.enabled", value, NULL);
1231 if (!(atoi(value) || !strncmp("true", value, 4)))
1232 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1233
1234 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1235 for (i = 0; i < num_usecase; i++) {
1236 if (!(adev->offload_usecases_state & (0x1<<i))) {
1237 adev->offload_usecases_state |= 0x1 << i;
1238 ret = offload_usecases[i];
1239 break;
1240 }
1241 }
1242 ALOGV("%s: offload usecase is %d", __func__, ret);
1243 return ret;
1244}
1245
1246static void free_offload_usecase(struct audio_device *adev,
1247 audio_usecase_t uc_id)
1248{
1249 unsigned int i;
1250 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1251 if (offload_usecases[i] == uc_id) {
1252 adev->offload_usecases_state &= ~(0x1<<i);
1253 break;
1254 }
1255 }
1256 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1257}
1258
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001259static void *offload_thread_loop(void *context)
1260{
1261 struct stream_out *out = (struct stream_out *) context;
1262 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001263 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001264
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001265 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1266 set_sched_policy(0, SP_FOREGROUND);
1267 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1268
1269 ALOGV("%s", __func__);
1270 pthread_mutex_lock(&out->lock);
1271 for (;;) {
1272 struct offload_cmd *cmd = NULL;
1273 stream_callback_event_t event;
1274 bool send_callback = false;
1275
1276 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1277 __func__, list_empty(&out->offload_cmd_list),
1278 out->offload_state);
1279 if (list_empty(&out->offload_cmd_list)) {
1280 ALOGV("%s SLEEPING", __func__);
1281 pthread_cond_wait(&out->offload_cond, &out->lock);
1282 ALOGV("%s RUNNING", __func__);
1283 continue;
1284 }
1285
1286 item = list_head(&out->offload_cmd_list);
1287 cmd = node_to_item(item, struct offload_cmd, node);
1288 list_remove(item);
1289
1290 ALOGVV("%s STATE %d CMD %d out->compr %p",
1291 __func__, out->offload_state, cmd->cmd, out->compr);
1292
1293 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1294 free(cmd);
1295 break;
1296 }
1297
1298 if (out->compr == NULL) {
1299 ALOGE("%s: Compress handle is NULL", __func__);
1300 pthread_cond_signal(&out->cond);
1301 continue;
1302 }
1303 out->offload_thread_blocked = true;
1304 pthread_mutex_unlock(&out->lock);
1305 send_callback = false;
1306 switch(cmd->cmd) {
1307 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001308 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001309 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001310 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001311 send_callback = true;
1312 event = STREAM_CBK_EVENT_WRITE_READY;
1313 break;
1314 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001315 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301316 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001317 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301318 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001319 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301320 if (ret < 0)
1321 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301322 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301323 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001324 compress_drain(out->compr);
1325 else
1326 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301327 if (ret != -ENETRESET) {
1328 send_callback = true;
1329 event = STREAM_CBK_EVENT_DRAIN_READY;
1330 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1331 } else
1332 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001333 break;
1334 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001335 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001336 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001337 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001338 send_callback = true;
1339 event = STREAM_CBK_EVENT_DRAIN_READY;
1340 break;
1341 default:
1342 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1343 break;
1344 }
1345 pthread_mutex_lock(&out->lock);
1346 out->offload_thread_blocked = false;
1347 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001348 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001349 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001350 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001351 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001352 free(cmd);
1353 }
1354
1355 pthread_cond_signal(&out->cond);
1356 while (!list_empty(&out->offload_cmd_list)) {
1357 item = list_head(&out->offload_cmd_list);
1358 list_remove(item);
1359 free(node_to_item(item, struct offload_cmd, node));
1360 }
1361 pthread_mutex_unlock(&out->lock);
1362
1363 return NULL;
1364}
1365
1366static int create_offload_callback_thread(struct stream_out *out)
1367{
1368 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1369 list_init(&out->offload_cmd_list);
1370 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1371 offload_thread_loop, out);
1372 return 0;
1373}
1374
1375static int destroy_offload_callback_thread(struct stream_out *out)
1376{
1377 pthread_mutex_lock(&out->lock);
1378 stop_compressed_output_l(out);
1379 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1380
1381 pthread_mutex_unlock(&out->lock);
1382 pthread_join(out->offload_thread, (void **) NULL);
1383 pthread_cond_destroy(&out->offload_cond);
1384
1385 return 0;
1386}
1387
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388static bool allow_hdmi_channel_config(struct audio_device *adev)
1389{
1390 struct listnode *node;
1391 struct audio_usecase *usecase;
1392 bool ret = true;
1393
1394 list_for_each(node, &adev->usecase_list) {
1395 usecase = node_to_item(node, struct audio_usecase, list);
1396 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1397 /*
1398 * If voice call is already existing, do not proceed further to avoid
1399 * disabling/enabling both RX and TX devices, CSD calls, etc.
1400 * Once the voice call done, the HDMI channels can be configured to
1401 * max channels of remaining use cases.
1402 */
1403 if (usecase->id == USECASE_VOICE_CALL) {
1404 ALOGD("%s: voice call is active, no change in HDMI channels",
1405 __func__);
1406 ret = false;
1407 break;
1408 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1409 ALOGD("%s: multi channel playback is active, "
1410 "no change in HDMI channels", __func__);
1411 ret = false;
1412 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001413 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001414 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001415 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1416 ", no change in HDMI channels", __func__,
1417 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001418 ret = false;
1419 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001420 }
1421 }
1422 }
1423 return ret;
1424}
1425
1426static int check_and_set_hdmi_channels(struct audio_device *adev,
1427 unsigned int channels)
1428{
1429 struct listnode *node;
1430 struct audio_usecase *usecase;
1431
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001432 unsigned int supported_channels = platform_edid_get_max_channels(
1433 adev->platform);
1434 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001435 /* Check if change in HDMI channel config is allowed */
1436 if (!allow_hdmi_channel_config(adev))
1437 return 0;
1438
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001439 if (channels > supported_channels)
1440 channels = supported_channels;
1441
Eric Laurent07eeafd2013-10-06 12:52:49 -07001442 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001443 ALOGD("%s: Requested channels are same as current channels(%d)",
1444 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001445 return 0;
1446 }
1447
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001448 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001449 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001450 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001451 adev->cur_hdmi_channels = channels;
1452
1453 /*
1454 * Deroute all the playback streams routed to HDMI so that
1455 * the back end is deactivated. Note that backend will not
1456 * be deactivated if any one stream is connected to it.
1457 */
1458 list_for_each(node, &adev->usecase_list) {
1459 usecase = node_to_item(node, struct audio_usecase, list);
1460 if (usecase->type == PCM_PLAYBACK &&
1461 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001463 }
1464 }
1465
1466 /*
1467 * Enable all the streams disabled above. Now the HDMI backend
1468 * will be activated with new channel configuration
1469 */
1470 list_for_each(node, &adev->usecase_list) {
1471 usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_PLAYBACK &&
1473 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001474 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001475 }
1476 }
1477
1478 return 0;
1479}
1480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481static int stop_output_stream(struct stream_out *out)
1482{
1483 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 struct audio_usecase *uc_info;
1485 struct audio_device *adev = out->dev;
1486
Eric Laurent994a6932013-07-17 11:51:42 -07001487 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 uc_info = get_usecase_from_list(adev, out->usecase);
1490 if (uc_info == NULL) {
1491 ALOGE("%s: Could not find the usecase (%d) in the list",
1492 __func__, out->usecase);
1493 return -EINVAL;
1494 }
1495
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001496 if (is_offload_usecase(out->usecase) &&
1497 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001498 if (adev->visualizer_stop_output != NULL)
1499 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001500
1501 audio_extn_dts_remove_state_notifier_node(out->usecase);
1502
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001503 if (adev->offload_effects_stop_output != NULL)
1504 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1505 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001506
Eric Laurent150dbfe2013-02-27 14:31:02 -08001507 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001508 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001509
1510 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001511 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001513 list_remove(&uc_info->list);
1514 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001516 if (is_offload_usecase(out->usecase) &&
1517 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1518 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1519 ALOGV("Disable passthrough , reset mixer to pcm");
1520 /* NO_PASSTHROUGH */
1521 out->compr_config.codec->compr_passthr = 0;
1522 audio_extn_dolby_set_hdmi_config(adev, out);
1523 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1524 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001525 /* Must be called after removing the usecase from list */
1526 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1527 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1528
Eric Laurent994a6932013-07-17 11:51:42 -07001529 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 return ret;
1531}
1532
1533int start_output_stream(struct stream_out *out)
1534{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001536 int sink_channels = 0;
1537 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 struct audio_usecase *uc_info;
1539 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301540 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001542 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1543 ret = -EINVAL;
1544 goto error_config;
1545 }
1546
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301547 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1548 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1549 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301550
Naresh Tanniru80659832014-06-04 18:17:56 +05301551 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301552 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301553 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301554 goto error_config;
1555 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301556
Eric Laurentb23d5282013-05-14 15:27:20 -07001557 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558 if (out->pcm_device_id < 0) {
1559 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1560 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001561 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001562 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563 }
1564
1565 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001566
1567 if (!uc_info) {
1568 ret = -ENOMEM;
1569 goto error_config;
1570 }
1571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 uc_info->id = out->usecase;
1573 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001574 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 uc_info->devices = out->devices;
1576 uc_info->in_snd_device = SND_DEVICE_NONE;
1577 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001578 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001579 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001580 if (is_offload_usecase(out->usecase)) {
1581 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001582 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1583 }
1584 }
Mingming Yin9c041392014-05-01 15:37:31 -07001585 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1586 if (!strncmp("true", prop_value, 4)) {
1587 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001588 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1589 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001590 check_and_set_hdmi_channels(adev, sink_channels);
1591 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001592 if (is_offload_usecase(out->usecase)) {
1593 unsigned int ch_count = out->compr_config.codec->ch_in;
1594 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1595 /* backend channel config for passthrough stream is stereo */
1596 ch_count = 2;
1597 check_and_set_hdmi_channels(adev, ch_count);
1598 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001599 check_and_set_hdmi_channels(adev, out->config.channels);
1600 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001601 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001602 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001603 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 select_devices(adev, out->usecase);
1606
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001607 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1608 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001609 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001610 unsigned int flags = PCM_OUT;
1611 unsigned int pcm_open_retry_count = 0;
1612 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1613 flags |= PCM_MMAP | PCM_NOIRQ;
1614 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1615 } else
1616 flags |= PCM_MONOTONIC;
1617
1618 while (1) {
1619 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1620 flags, &out->config);
1621 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1622 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1623 if (out->pcm != NULL) {
1624 pcm_close(out->pcm);
1625 out->pcm = NULL;
1626 }
1627 if (pcm_open_retry_count-- == 0) {
1628 ret = -EIO;
1629 goto error_open;
1630 }
1631 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1632 continue;
1633 }
1634 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001635 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001636
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001637 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1638 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001639
1640 ALOGV("%s: pcm_prepare start", __func__);
1641 if (pcm_is_ready(out->pcm))
1642 pcm_prepare(out->pcm);
1643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001644 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001645 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1646 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001648 out->compr = compress_open(adev->snd_card,
1649 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001650 COMPRESS_IN, &out->compr_config);
1651 if (out->compr && !is_compress_ready(out->compr)) {
1652 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1653 compress_close(out->compr);
1654 out->compr = NULL;
1655 ret = -EIO;
1656 goto error_open;
1657 }
1658 if (out->offload_callback)
1659 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001660
Fred Oh3f43e742015-03-04 18:42:34 -08001661 /* Since small bufs uses blocking writes, a write will be blocked
1662 for the default max poll time (20s) in the event of an SSR.
1663 Reduce the poll time to observe and deal with SSR faster.
1664 */
1665 if (out->use_small_bufs) {
1666 compress_set_max_poll_wait(out->compr, 1000);
1667 }
1668
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001669 audio_extn_dts_create_state_notifier_node(out->usecase);
1670 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1671 popcount(out->channel_mask),
1672 out->playback_started);
1673
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001674#ifdef DS1_DOLBY_DDP_ENABLED
1675 if (audio_extn_is_dolby_format(out->format))
1676 audio_extn_dolby_send_ddp_endp_params(adev);
1677#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001678 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1679 if (adev->visualizer_start_output != NULL)
1680 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1681 if (adev->offload_effects_start_output != NULL)
1682 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001683 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001684 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001686
Eric Laurent994a6932013-07-17 11:51:42 -07001687 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001690error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001692error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001693 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694}
1695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696static int check_input_parameters(uint32_t sample_rate,
1697 audio_format_t format,
1698 int channel_count)
1699{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001700 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001702 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001703 !voice_extn_compress_voip_is_format_supported(format) &&
1704 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001705
1706 switch (channel_count) {
1707 case 1:
1708 case 2:
1709 case 6:
1710 break;
1711 default:
1712 ret = -EINVAL;
1713 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714
1715 switch (sample_rate) {
1716 case 8000:
1717 case 11025:
1718 case 12000:
1719 case 16000:
1720 case 22050:
1721 case 24000:
1722 case 32000:
1723 case 44100:
1724 case 48000:
1725 break;
1726 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001727 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728 }
1729
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001730 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731}
1732
1733static size_t get_input_buffer_size(uint32_t sample_rate,
1734 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001735 int channel_count,
1736 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737{
1738 size_t size = 0;
1739
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001740 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1741 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001743 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001744 if (is_low_latency)
1745 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001746 /* ToDo: should use frame_size computed based on the format and
1747 channel_count here. */
1748 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001750 /* make sure the size is multiple of 32 bytes
1751 * At 48 kHz mono 16-bit PCM:
1752 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1753 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1754 */
1755 size += 0x1f;
1756 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001757
1758 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759}
1760
1761static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1762{
1763 struct stream_out *out = (struct stream_out *)stream;
1764
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766}
1767
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001768static int out_set_sample_rate(struct audio_stream *stream __unused,
1769 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770{
1771 return -ENOSYS;
1772}
1773
1774static size_t out_get_buffer_size(const struct audio_stream *stream)
1775{
1776 struct stream_out *out = (struct stream_out *)stream;
1777
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001778 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001780 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1781 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001783 return out->config.period_size *
1784 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785}
1786
1787static uint32_t out_get_channels(const struct audio_stream *stream)
1788{
1789 struct stream_out *out = (struct stream_out *)stream;
1790
1791 return out->channel_mask;
1792}
1793
1794static audio_format_t out_get_format(const struct audio_stream *stream)
1795{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 struct stream_out *out = (struct stream_out *)stream;
1797
1798 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799}
1800
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001801static int out_set_format(struct audio_stream *stream __unused,
1802 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803{
1804 return -ENOSYS;
1805}
1806
1807static int out_standby(struct audio_stream *stream)
1808{
1809 struct stream_out *out = (struct stream_out *)stream;
1810 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001811
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301812 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1813 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001814 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1815 /* Ignore standby in case of voip call because the voip output
1816 * stream is closed in adev_close_output_stream()
1817 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301818 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001819 return 0;
1820 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001824 if (adev->adm_deregister_stream)
1825 adev->adm_deregister_stream(adev->adm_data, out->handle);
1826
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001827 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001829 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001830 if (out->pcm) {
1831 pcm_close(out->pcm);
1832 out->pcm = NULL;
1833 }
1834 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001835 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001837 out->gapless_mdata.encoder_delay = 0;
1838 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 if (out->compr != NULL) {
1840 compress_close(out->compr);
1841 out->compr = NULL;
1842 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001843 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001845 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 }
1847 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 return 0;
1850}
1851
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001852static int out_dump(const struct audio_stream *stream __unused,
1853 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854{
1855 return 0;
1856}
1857
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001858static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1859{
1860 int ret = 0;
1861 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001862 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001863
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001864 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001865 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 return -EINVAL;
1867 }
1868
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301869 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001870
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001871 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1872 if(ret >= 0)
1873 is_meta_data_params = true;
1874 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301875 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001876 is_meta_data_params = true;
1877 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301878 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001879 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001880 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1881 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001882 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301883 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001884 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001885 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1886 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001887 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301888 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001889 }
1890
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001891 if(!is_meta_data_params) {
1892 ALOGV("%s: Not gapless meta data params", __func__);
1893 return 0;
1894 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001895 out->send_new_metadata = 1;
1896 ALOGV("%s new encoder delay %u and padding %u", __func__,
1897 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1898
1899 return 0;
1900}
1901
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001902static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1903{
1904 return out == adev->primary_output || out == adev->voice_tx_output;
1905}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1908{
1909 struct stream_out *out = (struct stream_out *)stream;
1910 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001911 struct audio_usecase *usecase;
1912 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 struct str_parms *parms;
1914 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001915 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001916 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917
sangwoobc677242013-08-08 16:53:43 +09001918 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301921 if (!parms)
1922 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001923 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1924 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001927 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001929 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301930 * When HDMI cable is unplugged/usb hs is disconnected the
1931 * music playback is paused and the policy manager sends routing=0
1932 * But the audioflingercontinues to write data until standby time
1933 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001934 * Avoid this by routing audio to speaker until standby.
1935 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301936 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1937 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001938 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001939 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1940 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001941 }
1942
1943 /*
1944 * select_devices() call below switches all the usecases on the same
1945 * backend to the new device. Refer to check_usecases_codec_backend() in
1946 * the select_devices(). But how do we undo this?
1947 *
1948 * For example, music playback is active on headset (deep-buffer usecase)
1949 * and if we go to ringtones and select a ringtone, low-latency usecase
1950 * will be started on headset+speaker. As we can't enable headset+speaker
1951 * and headset devices at the same time, select_devices() switches the music
1952 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1953 * So when the ringtone playback is completed, how do we undo the same?
1954 *
1955 * We are relying on the out_set_parameters() call on deep-buffer output,
1956 * once the ringtone playback is ended.
1957 * NOTE: We should not check if the current devices are same as new devices.
1958 * Because select_devices() must be called to switch back the music
1959 * playback to headset.
1960 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001961 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001962 out->devices = val;
1963
1964 if (!out->standby)
1965 select_devices(adev, out->usecase);
1966
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001967 if (output_drives_call(adev, out)) {
1968 if(!voice_is_in_call(adev)) {
1969 if (adev->mode == AUDIO_MODE_IN_CALL) {
1970 adev->current_call_output = out;
1971 ret = voice_start_call(adev);
1972 }
1973 } else {
1974 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001975 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001976 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001977 }
1978 }
1979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001981 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001983
1984 if (out == adev->primary_output) {
1985 pthread_mutex_lock(&adev->lock);
1986 audio_extn_set_parameters(adev, parms);
1987 pthread_mutex_unlock(&adev->lock);
1988 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001989 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001990 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001991 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001992
1993 audio_extn_dts_create_state_notifier_node(out->usecase);
1994 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1995 popcount(out->channel_mask),
1996 out->playback_started);
1997
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001998 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001999 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302002error:
Eric Laurent994a6932013-07-17 11:51:42 -07002003 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 return ret;
2005}
2006
2007static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2008{
2009 struct stream_out *out = (struct stream_out *)stream;
2010 struct str_parms *query = str_parms_create_str(keys);
2011 char *str;
2012 char value[256];
2013 struct str_parms *reply = str_parms_create();
2014 size_t i, j;
2015 int ret;
2016 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002017
2018 if (!query || !reply) {
2019 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2020 return NULL;
2021 }
2022
Eric Laurent994a6932013-07-17 11:51:42 -07002023 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2025 if (ret >= 0) {
2026 value[0] = '\0';
2027 i = 0;
2028 while (out->supported_channel_masks[i] != 0) {
2029 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2030 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2031 if (!first) {
2032 strcat(value, "|");
2033 }
2034 strcat(value, out_channels_name_to_enum_table[j].name);
2035 first = false;
2036 break;
2037 }
2038 }
2039 i++;
2040 }
2041 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2042 str = str_parms_to_str(reply);
2043 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002044 voice_extn_out_get_parameters(out, query, reply);
2045 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002046 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002047 free(str);
2048 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002049 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002051
2052 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2053 if (ret >= 0) {
2054 value[0] = '\0';
2055 i = 0;
2056 first = true;
2057 while (out->supported_formats[i] != 0) {
2058 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2059 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2060 if (!first) {
2061 strcat(value, "|");
2062 }
2063 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2064 first = false;
2065 break;
2066 }
2067 }
2068 i++;
2069 }
2070 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2071 str = str_parms_to_str(reply);
2072 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 str_parms_destroy(query);
2074 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002075 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 return str;
2077}
2078
2079static uint32_t out_get_latency(const struct audio_stream_out *stream)
2080{
2081 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002082 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083
Alexy Josephaa54c872014-12-03 02:46:47 -08002084 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002085 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002086 } else {
2087 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002088 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002089 }
2090
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302091 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002092 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093}
2094
2095static int out_set_volume(struct audio_stream_out *stream, float left,
2096 float right)
2097{
Eric Laurenta9024de2013-04-04 09:19:12 -07002098 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 int volume[2];
2100
Eric Laurenta9024de2013-04-04 09:19:12 -07002101 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2102 /* only take left channel into account: the API is for stereo anyway */
2103 out->muted = (left == 0.0f);
2104 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002105 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002106 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2107 /*
2108 * Set mute or umute on HDMI passthrough stream.
2109 * Only take left channel into account.
2110 * Mute is 0 and unmute 1
2111 */
2112 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2113 } else {
2114 char mixer_ctl_name[128];
2115 struct audio_device *adev = out->dev;
2116 struct mixer_ctl *ctl;
2117 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002118 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002120 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2121 "Compress Playback %d Volume", pcm_device_id);
2122 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2123 if (!ctl) {
2124 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2125 __func__, mixer_ctl_name);
2126 return -EINVAL;
2127 }
2128 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2129 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2130 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2131 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002133 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135 return -ENOSYS;
2136}
2137
2138static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2139 size_t bytes)
2140{
2141 struct stream_out *out = (struct stream_out *)stream;
2142 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302143 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002144 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302147
Naresh Tanniru80659832014-06-04 18:17:56 +05302148 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002149 // increase written size during SSR to avoid mismatch
2150 // with the written frames count in AF
2151 if (!is_offload_usecase(out->usecase))
2152 out->written += bytes / (out->config.channels * sizeof(short));
2153
Naresh Tanniru80659832014-06-04 18:17:56 +05302154 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302155 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302156 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302157 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002158 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302159 //during SSR for compress usecase we should return error to flinger
2160 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2161 pthread_mutex_unlock(&out->lock);
2162 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302163 }
2164 }
2165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002167 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002168 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002169 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2170 ret = voice_extn_compress_voip_start_output_stream(out);
2171 else
2172 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002173 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002176 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 goto exit;
2178 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002179 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2180 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002183 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002184 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002185 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002186 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002187 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2188 out->send_new_metadata = 0;
2189 }
2190
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302192 if (ret < 0)
2193 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002194 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002195 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302196 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302198 } else if (-ENETRESET == ret) {
2199 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2200 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2201 pthread_mutex_unlock(&out->lock);
2202 out_standby(&out->stream.common);
2203 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302205 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002207 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 out->playback_started = 1;
2209 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002210
2211 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2212 popcount(out->channel_mask),
2213 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 }
2215 pthread_mutex_unlock(&out->lock);
2216 return ret;
2217 } else {
2218 if (out->pcm) {
2219 if (out->muted)
2220 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002223
2224 if (adev->adm_request_focus)
2225 adev->adm_request_focus(adev->adm_data, out->handle);
2226
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002227 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2228 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2229 else
2230 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002231
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302232 if (ret < 0)
2233 ret = -errno;
2234 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002235 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002236
2237 if (adev->adm_abandon_focus)
2238 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 }
2241
2242exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302243 /* ToDo: There may be a corner case when SSR happens back to back during
2244 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302245 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302246 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302247 }
2248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 pthread_mutex_unlock(&out->lock);
2250
2251 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002252 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002253 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302254 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302255 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302256 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302257 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302258 out->standby = true;
2259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002261 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302262 out_get_sample_rate(&out->stream.common));
2263
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 }
2265 return bytes;
2266}
2267
2268static int out_get_render_position(const struct audio_stream_out *stream,
2269 uint32_t *dsp_frames)
2270{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302272 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002273
2274 if (dsp_frames == NULL)
2275 return -EINVAL;
2276
2277 *dsp_frames = 0;
2278 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002279 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 pthread_mutex_lock(&out->lock);
2281 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302282 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002283 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302284 if (ret < 0)
2285 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 ALOGVV("%s rendered frames %d sample_rate %d",
2287 __func__, *dsp_frames, out->sample_rate);
2288 }
2289 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302290 if (-ENETRESET == ret) {
2291 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2292 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2293 return -EINVAL;
2294 } else if(ret < 0) {
2295 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2296 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302297 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2298 /*
2299 * Handle corner case where compress session is closed during SSR
2300 * and timestamp is queried
2301 */
2302 ALOGE(" ERROR: sound card not active, return error");
2303 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302304 } else {
2305 return 0;
2306 }
Zhou Song32a556e2015-05-05 10:46:56 +08002307 } else if (audio_is_linear_pcm(out->format)) {
2308 *dsp_frames = out->written;
2309 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 } else
2311 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312}
2313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002314static int out_add_audio_effect(const struct audio_stream *stream __unused,
2315 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316{
2317 return 0;
2318}
2319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002320static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2321 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322{
2323 return 0;
2324}
2325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002326static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2327 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328{
2329 return -EINVAL;
2330}
2331
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002332static int out_get_presentation_position(const struct audio_stream_out *stream,
2333 uint64_t *frames, struct timespec *timestamp)
2334{
2335 struct stream_out *out = (struct stream_out *)stream;
2336 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002337 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002338
2339 pthread_mutex_lock(&out->lock);
2340
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002341 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002342 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302343 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002344 &out->sample_rate);
2345 ALOGVV("%s rendered frames %ld sample_rate %d",
2346 __func__, dsp_frames, out->sample_rate);
2347 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302348 if (ret < 0)
2349 ret = -errno;
2350 if (-ENETRESET == ret) {
2351 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2352 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2353 ret = -EINVAL;
2354 } else
2355 ret = 0;
2356
Eric Laurent949a0892013-09-20 09:20:13 -07002357 /* this is the best we can do */
2358 clock_gettime(CLOCK_MONOTONIC, timestamp);
2359 }
2360 } else {
2361 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002362 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002363 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2364 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002365 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002366 // This adjustment accounts for buffering after app processor.
2367 // It is based on estimated DSP latency per use case, rather than exact.
2368 signed_frames -=
2369 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2370
Eric Laurent949a0892013-09-20 09:20:13 -07002371 // It would be unusual for this value to be negative, but check just in case ...
2372 if (signed_frames >= 0) {
2373 *frames = signed_frames;
2374 ret = 0;
2375 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002376 }
2377 }
2378 }
2379
2380 pthread_mutex_unlock(&out->lock);
2381
2382 return ret;
2383}
2384
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385static int out_set_callback(struct audio_stream_out *stream,
2386 stream_callback_t callback, void *cookie)
2387{
2388 struct stream_out *out = (struct stream_out *)stream;
2389
2390 ALOGV("%s", __func__);
2391 pthread_mutex_lock(&out->lock);
2392 out->offload_callback = callback;
2393 out->offload_cookie = cookie;
2394 pthread_mutex_unlock(&out->lock);
2395 return 0;
2396}
2397
2398static int out_pause(struct audio_stream_out* stream)
2399{
2400 struct stream_out *out = (struct stream_out *)stream;
2401 int status = -ENOSYS;
2402 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002403 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002404 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 pthread_mutex_lock(&out->lock);
2406 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302407 struct audio_device *adev = out->dev;
2408 int snd_scard_state = get_snd_card_state(adev);
2409
2410 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2411 status = compress_pause(out->compr);
2412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002414
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302415 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002416 audio_extn_dts_notify_playback_state(out->usecase, 0,
2417 out->sample_rate, popcount(out->channel_mask),
2418 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 }
2420 pthread_mutex_unlock(&out->lock);
2421 }
2422 return status;
2423}
2424
2425static int out_resume(struct audio_stream_out* stream)
2426{
2427 struct stream_out *out = (struct stream_out *)stream;
2428 int status = -ENOSYS;
2429 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002430 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002431 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002432 status = 0;
2433 pthread_mutex_lock(&out->lock);
2434 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302435 struct audio_device *adev = out->dev;
2436 int snd_scard_state = get_snd_card_state(adev);
2437
2438 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2439 status = compress_resume(out->compr);
2440
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002442
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302443 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002444 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2445 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002446 }
2447 pthread_mutex_unlock(&out->lock);
2448 }
2449 return status;
2450}
2451
2452static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2453{
2454 struct stream_out *out = (struct stream_out *)stream;
2455 int status = -ENOSYS;
2456 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002457 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458 pthread_mutex_lock(&out->lock);
2459 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2460 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2461 else
2462 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2463 pthread_mutex_unlock(&out->lock);
2464 }
2465 return status;
2466}
2467
2468static int out_flush(struct audio_stream_out* stream)
2469{
2470 struct stream_out *out = (struct stream_out *)stream;
2471 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002472 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002473 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 pthread_mutex_lock(&out->lock);
2475 stop_compressed_output_l(out);
2476 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002477 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002478 return 0;
2479 }
2480 return -ENOSYS;
2481}
2482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483/** audio_stream_in implementation **/
2484static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2485{
2486 struct stream_in *in = (struct stream_in *)stream;
2487
2488 return in->config.rate;
2489}
2490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002491static int in_set_sample_rate(struct audio_stream *stream __unused,
2492 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493{
2494 return -ENOSYS;
2495}
2496
2497static size_t in_get_buffer_size(const struct audio_stream *stream)
2498{
2499 struct stream_in *in = (struct stream_in *)stream;
2500
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002501 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2502 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002503 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2504 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002505
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002506 return in->config.period_size *
2507 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508}
2509
2510static uint32_t in_get_channels(const struct audio_stream *stream)
2511{
2512 struct stream_in *in = (struct stream_in *)stream;
2513
2514 return in->channel_mask;
2515}
2516
2517static audio_format_t in_get_format(const struct audio_stream *stream)
2518{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002519 struct stream_in *in = (struct stream_in *)stream;
2520
2521 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522}
2523
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002524static int in_set_format(struct audio_stream *stream __unused,
2525 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526{
2527 return -ENOSYS;
2528}
2529
2530static int in_standby(struct audio_stream *stream)
2531{
2532 struct stream_in *in = (struct stream_in *)stream;
2533 struct audio_device *adev = in->dev;
2534 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302535 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2536 stream, in->usecase, use_case_table[in->usecase]);
2537
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002538 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2539 /* Ignore standby in case of voip call because the voip input
2540 * stream is closed in adev_close_input_stream()
2541 */
2542 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2543 return status;
2544 }
2545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002547 if (!in->standby && in->is_st_session) {
2548 ALOGD("%s: sound trigger pcm stop lab", __func__);
2549 audio_extn_sound_trigger_stop_lab(in);
2550 in->standby = 1;
2551 }
2552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002554 if (adev->adm_deregister_stream)
2555 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2556
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002557 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002559 if (in->pcm) {
2560 pcm_close(in->pcm);
2561 in->pcm = NULL;
2562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002564 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 }
2566 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002567 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 return status;
2569}
2570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002571static int in_dump(const struct audio_stream *stream __unused,
2572 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573{
2574 return 0;
2575}
2576
2577static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2578{
2579 struct stream_in *in = (struct stream_in *)stream;
2580 struct audio_device *adev = in->dev;
2581 struct str_parms *parms;
2582 char *str;
2583 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002584 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302586 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 parms = str_parms_create_str(kvpairs);
2588
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302589 if (!parms)
2590 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002592 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002593
2594 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2595 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 val = atoi(value);
2597 /* no audio source uses val == 0 */
2598 if ((in->source != val) && (val != 0)) {
2599 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002600 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2601 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2602 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2603 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002604 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002605 err = voice_extn_compress_voip_open_input_stream(in);
2606 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002607 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002608 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002609 }
2610 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
2612 }
2613
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002614 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2615 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002617 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 in->device = val;
2619 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002620 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002621 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 }
2623 }
2624
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002625done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002627 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
2629 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302630error:
Eric Laurent994a6932013-07-17 11:51:42 -07002631 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 return ret;
2633}
2634
2635static char* in_get_parameters(const struct audio_stream *stream,
2636 const char *keys)
2637{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002638 struct stream_in *in = (struct stream_in *)stream;
2639 struct str_parms *query = str_parms_create_str(keys);
2640 char *str;
2641 char value[256];
2642 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002643
2644 if (!query || !reply) {
2645 ALOGE("in_get_parameters: failed to create query or reply");
2646 return NULL;
2647 }
2648
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002649 ALOGV("%s: enter: keys - %s", __func__, keys);
2650
2651 voice_extn_in_get_parameters(in, query, reply);
2652
2653 str = str_parms_to_str(reply);
2654 str_parms_destroy(query);
2655 str_parms_destroy(reply);
2656
2657 ALOGV("%s: exit: returns - %s", __func__, str);
2658 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659}
2660
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002661static int in_set_gain(struct audio_stream_in *stream __unused,
2662 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663{
2664 return 0;
2665}
2666
2667static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2668 size_t bytes)
2669{
2670 struct stream_in *in = (struct stream_in *)stream;
2671 struct audio_device *adev = in->dev;
2672 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302673 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302676
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002677 if (in->is_st_session) {
2678 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2679 /* Read from sound trigger HAL */
2680 audio_extn_sound_trigger_read(in, buffer, bytes);
2681 pthread_mutex_unlock(&in->lock);
2682 return bytes;
2683 }
2684
2685 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2686 ALOGD(" %s: sound card is not active/SSR state", __func__);
2687 ret= -EIO;;
2688 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302689 }
2690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002692 pthread_mutex_lock(&adev->lock);
2693 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2694 ret = voice_extn_compress_voip_start_input_stream(in);
2695 else
2696 ret = start_input_stream(in);
2697 pthread_mutex_unlock(&adev->lock);
2698 if (ret != 0) {
2699 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 }
2701 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002702 if (adev->adm_register_input_stream)
2703 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002706 if (adev->adm_request_focus)
2707 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002710 if (audio_extn_ssr_get_enabled() &&
2711 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002712 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002713 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2714 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002715 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2716 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002717 else
2718 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302719 if (ret < 0)
2720 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 }
2722
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002723 if (adev->adm_abandon_focus)
2724 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 /*
2727 * Instead of writing zeroes here, we could trust the hardware
2728 * to always provide zeroes when muted.
2729 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302730 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2731 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 memset(buffer, 0, bytes);
2733
2734exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302735 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302736 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002737 if (-ENETRESET == ret)
2738 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 pthread_mutex_unlock(&in->lock);
2741
2742 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302743 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302744 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302745 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302746 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302747 in->standby = true;
2748 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302749 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002751 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002752 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302753 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 }
2755 return bytes;
2756}
2757
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002758static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759{
2760 return 0;
2761}
2762
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002763static int add_remove_audio_effect(const struct audio_stream *stream,
2764 effect_handle_t effect,
2765 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002767 struct stream_in *in = (struct stream_in *)stream;
2768 int status = 0;
2769 effect_descriptor_t desc;
2770
2771 status = (*effect)->get_descriptor(effect, &desc);
2772 if (status != 0)
2773 return status;
2774
2775 pthread_mutex_lock(&in->lock);
2776 pthread_mutex_lock(&in->dev->lock);
2777 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2778 in->enable_aec != enable &&
2779 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2780 in->enable_aec = enable;
2781 if (!in->standby)
2782 select_devices(in->dev, in->usecase);
2783 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002784 if (in->enable_ns != enable &&
2785 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2786 in->enable_ns = enable;
2787 if (!in->standby)
2788 select_devices(in->dev, in->usecase);
2789 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002790 pthread_mutex_unlock(&in->dev->lock);
2791 pthread_mutex_unlock(&in->lock);
2792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 return 0;
2794}
2795
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002796static int in_add_audio_effect(const struct audio_stream *stream,
2797 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798{
Eric Laurent994a6932013-07-17 11:51:42 -07002799 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002800 return add_remove_audio_effect(stream, effect, true);
2801}
2802
2803static int in_remove_audio_effect(const struct audio_stream *stream,
2804 effect_handle_t effect)
2805{
Eric Laurent994a6932013-07-17 11:51:42 -07002806 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002807 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808}
2809
2810static int adev_open_output_stream(struct audio_hw_device *dev,
2811 audio_io_handle_t handle,
2812 audio_devices_t devices,
2813 audio_output_flags_t flags,
2814 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002815 struct audio_stream_out **stream_out,
2816 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817{
2818 struct audio_device *adev = (struct audio_device *)dev;
2819 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002820 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002821 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302824
2825 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2826 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002827 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302828 return -EINVAL;
2829 }
2830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2832
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302833 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2834 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2835 devices, flags, &out->stream);
2836
2837
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002838 if (!out) {
2839 return -ENOMEM;
2840 }
2841
Haynes Mathew George204045b2015-02-25 20:32:03 -08002842 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2843 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 if (devices == AUDIO_DEVICE_NONE)
2846 devices = AUDIO_DEVICE_OUT_SPEAKER;
2847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848 out->flags = flags;
2849 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002850 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002851 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852 out->sample_rate = config->sample_rate;
2853 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2854 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002855 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002856 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002857 out->non_blocking = 0;
2858 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859
2860 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002861 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2862 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002863 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2864 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2865
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002866 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002867 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2868 ret = read_hdmi_channel_masks(out);
2869
2870 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2871 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002872 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002873 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002874 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002875
2876 if (config->sample_rate == 0)
2877 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2878 if (config->channel_mask == 0)
2879 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2880
2881 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2884 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002886 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002888 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2889 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002890 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002891 ret = voice_extn_compress_voip_open_output_stream(out);
2892 if (ret != 0) {
2893 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2894 __func__, ret);
2895 goto error_open;
2896 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002897 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2898 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2899
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2901 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2902 ALOGE("%s: Unsupported Offload information", __func__);
2903 ret = -EINVAL;
2904 goto error_open;
2905 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002906
2907 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2908 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2909 ALOGV("read and update_pass through formats");
2910 ret = audio_extn_dolby_update_passt_formats(adev, out);
2911 if(ret != 0) {
2912 goto error_open;
2913 }
2914 if(config->offload_info.format == 0)
2915 config->offload_info.format = out->supported_formats[0];
2916 }
2917
Mingming Yin90310102013-11-13 16:57:00 -08002918 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002919 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002920 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 ret = -EINVAL;
2922 goto error_open;
2923 }
2924
2925 out->compr_config.codec = (struct snd_codec *)
2926 calloc(1, sizeof(struct snd_codec));
2927
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002928 if (!out->compr_config.codec) {
2929 ret = -ENOMEM;
2930 goto error_open;
2931 }
2932
vivek mehta0ea887a2015-08-26 14:01:20 -07002933 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2934 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2935 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2936 } else {
2937 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2938 out->usecase = get_offload_usecase(adev);
2939 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 if (config->offload_info.channel_mask)
2941 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002942 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002944 config->offload_info.channel_mask = config->channel_mask;
2945 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002946 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 out->sample_rate = config->offload_info.sample_rate;
2948
2949 out->stream.set_callback = out_set_callback;
2950 out->stream.pause = out_pause;
2951 out->stream.resume = out_resume;
2952 out->stream.drain = out_drain;
2953 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002954 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002956 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002957 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002958 audio_extn_dolby_get_snd_codec_id(adev, out,
2959 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002960 else
2961 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002962 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07002963
2964 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2965 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002966 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002967 platform_get_pcm_offload_buffer_size(&config->offload_info);
2968 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2969 out->compr_config.fragment_size =
2970 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002971 } else {
2972 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002973 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002974 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002975 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2976 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002977 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 out->compr_config.codec->bit_rate =
2979 config->offload_info.bit_rate;
2980 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002981 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05302983 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002984 /*TODO: Do we need to change it for passthrough */
2985 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986
Manish Dewangana6fc5442015-08-24 20:30:31 +05302987 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2988 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2989 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2990 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002991 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2992 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002993 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002994 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07002995 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2996 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002997
Mingming Yin3ee55c62014-08-04 14:23:35 -07002998 if (out->bit_width == 24) {
2999 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3000 }
3001
Amit Shekhar6f461b12014-08-01 14:52:58 -07003002 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303003 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003004
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003005 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3006 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003007
Mingming Yin497419f2015-07-01 16:57:32 -07003008 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003009 //this flag is set from framework only if its for PCM formats
3010 //no need to check for PCM format again
3011 out->non_blocking = 0;
3012 out->use_small_bufs = true;
3013 ALOGI("Keep write blocking for small buff: non_blockling %d",
3014 out->non_blocking);
3015 }
3016
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003017 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003018 out->offload_state = OFFLOAD_STATE_IDLE;
3019 out->playback_started = 0;
3020
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003021 audio_extn_dts_create_state_notifier_node(out->usecase);
3022
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003023 create_offload_callback_thread(out);
3024 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3025 __func__, config->offload_info.version,
3026 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003027 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003028 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003029 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3030 ret = voice_check_and_set_incall_music_usecase(adev, out);
3031 if (ret != 0) {
3032 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3033 __func__, ret);
3034 goto error_open;
3035 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003036 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3037 if (config->sample_rate == 0)
3038 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3039 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3040 config->sample_rate != 8000) {
3041 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3042 ret = -EINVAL;
3043 goto error_open;
3044 }
3045 out->sample_rate = config->sample_rate;
3046 out->config.rate = config->sample_rate;
3047 if (config->format == AUDIO_FORMAT_DEFAULT)
3048 config->format = AUDIO_FORMAT_PCM_16_BIT;
3049 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3050 config->format = AUDIO_FORMAT_PCM_16_BIT;
3051 ret = -EINVAL;
3052 goto error_open;
3053 }
3054 out->format = config->format;
3055 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3056 out->config = pcm_config_afe_proxy_playback;
3057 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003058 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3059 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3060 out->config = pcm_config_low_latency;
3061 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003062 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003063 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3065 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003067 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3068 format = AUDIO_FORMAT_PCM_16_BIT;
3069 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3070 out->config = pcm_config_deep_buffer;
3071 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003072 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003073 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003074 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003075 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003076 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003077 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 }
3079
Amit Shekhar1d896042014-10-03 13:16:09 -07003080 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3081 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003082 /* TODO remove this hardcoding and check why width is zero*/
3083 if (out->bit_width == 0)
3084 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003085 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3086 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003087 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003088 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003089 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3090 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3091 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003092 if(adev->primary_output == NULL)
3093 adev->primary_output = out;
3094 else {
3095 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003096 ret = -EEXIST;
3097 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003098 }
3099 }
3100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 /* Check if this usecase is already existing */
3102 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003103 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3104 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003107 ret = -EEXIST;
3108 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 }
3110 pthread_mutex_unlock(&adev->lock);
3111
3112 out->stream.common.get_sample_rate = out_get_sample_rate;
3113 out->stream.common.set_sample_rate = out_set_sample_rate;
3114 out->stream.common.get_buffer_size = out_get_buffer_size;
3115 out->stream.common.get_channels = out_get_channels;
3116 out->stream.common.get_format = out_get_format;
3117 out->stream.common.set_format = out_set_format;
3118 out->stream.common.standby = out_standby;
3119 out->stream.common.dump = out_dump;
3120 out->stream.common.set_parameters = out_set_parameters;
3121 out->stream.common.get_parameters = out_get_parameters;
3122 out->stream.common.add_audio_effect = out_add_audio_effect;
3123 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3124 out->stream.get_latency = out_get_latency;
3125 out->stream.set_volume = out_set_volume;
3126 out->stream.write = out_write;
3127 out->stream.get_render_position = out_get_render_position;
3128 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003129 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003132 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003133 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
3135 config->format = out->stream.common.get_format(&out->stream.common);
3136 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3137 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3138
3139 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303140 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003141 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003142
3143 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3144 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3145 popcount(out->channel_mask), out->playback_started);
3146
Eric Laurent994a6932013-07-17 11:51:42 -07003147 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003149
3150error_open:
3151 free(out);
3152 *stream_out = NULL;
3153 ALOGD("%s: exit: ret %d", __func__, ret);
3154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155}
3156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003157static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 struct audio_stream_out *stream)
3159{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160 struct stream_out *out = (struct stream_out *)stream;
3161 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003162 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303164 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3165
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003166 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303167 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003168 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303169 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003170 if(ret != 0)
3171 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3172 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003173 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003174 out_standby(&stream->common);
3175
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003176 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003177 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003179 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 if (out->compr_config.codec != NULL)
3181 free(out->compr_config.codec);
3182 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003183
3184 if (adev->voice_tx_output == out)
3185 adev->voice_tx_output = NULL;
3186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 pthread_cond_destroy(&out->cond);
3188 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003190 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191}
3192
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003193static void close_compress_sessions(struct audio_device *adev)
3194{
Mingming Yin7b762e72015-03-04 13:47:32 -08003195 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303196 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003197 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003198 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303199
3200 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003201 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303202 if (is_offload_usecase(usecase->id)) {
3203 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003204 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3205 out = usecase->stream.out;
3206 pthread_mutex_unlock(&adev->lock);
3207 out_standby(&out->stream.common);
3208 pthread_mutex_lock(&adev->lock);
3209 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303210 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003211 }
3212 pthread_mutex_unlock(&adev->lock);
3213}
3214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3216{
3217 struct audio_device *adev = (struct audio_device *)dev;
3218 struct str_parms *parms;
3219 char *str;
3220 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003221 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003222 int ret;
3223 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003225 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303228 if (!parms)
3229 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003230 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3231 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303232 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303233 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303234 struct listnode *node;
3235 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303236 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303237 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003238 //close compress sessions on OFFLINE status
3239 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303240 } else if (strstr(snd_card_status, "ONLINE")) {
3241 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303242 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003243 //send dts hpx license if enabled
3244 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303245 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303246 }
3247
3248 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003249 status = voice_set_parameters(adev, parms);
3250 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003251 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003253 status = platform_set_parameters(adev->platform, parms);
3254 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003255 goto done;
3256
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003257 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3258 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003259 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3261 adev->bluetooth_nrec = true;
3262 else
3263 adev->bluetooth_nrec = false;
3264 }
3265
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003266 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3267 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3269 adev->screen_off = false;
3270 else
3271 adev->screen_off = true;
3272 }
3273
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003274 ret = str_parms_get_int(parms, "rotation", &val);
3275 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003276 bool reverse_speakers = false;
3277 switch(val) {
3278 // FIXME: note that the code below assumes that the speakers are in the correct placement
3279 // relative to the user when the device is rotated 90deg from its default rotation. This
3280 // assumption is device-specific, not platform-specific like this code.
3281 case 270:
3282 reverse_speakers = true;
3283 break;
3284 case 0:
3285 case 90:
3286 case 180:
3287 break;
3288 default:
3289 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003290 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003291 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003292 if (status == 0) {
3293 if (adev->speaker_lr_swap != reverse_speakers) {
3294 adev->speaker_lr_swap = reverse_speakers;
3295 // only update the selected device if there is active pcm playback
3296 struct audio_usecase *usecase;
3297 struct listnode *node;
3298 list_for_each(node, &adev->usecase_list) {
3299 usecase = node_to_item(node, struct audio_usecase, list);
3300 if (usecase->type == PCM_PLAYBACK) {
3301 select_devices(adev, usecase->id);
3302 break;
3303 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003304 }
3305 }
3306 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003307 }
3308
Mingming Yin514a8bc2014-07-29 15:22:21 -07003309 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3310 if (ret >= 0) {
3311 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3312 adev->bt_wb_speech_enabled = true;
3313 else
3314 adev->bt_wb_speech_enabled = false;
3315 }
3316
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003317 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3318 if (ret >= 0) {
3319 val = atoi(value);
3320 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3321 ALOGV("cache new edid");
3322 platform_cache_edid(adev->platform);
3323 }
3324 }
3325
3326 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3327 if (ret >= 0) {
3328 val = atoi(value);
3329 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3330 ALOGV("invalidate cached edid");
3331 platform_invalidate_edid(adev->platform);
3332 }
3333 }
3334
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003335 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003336
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003337done:
3338 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003339 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303340error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003341 ALOGV("%s: exit with code(%d)", __func__, status);
3342 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343}
3344
3345static char* adev_get_parameters(const struct audio_hw_device *dev,
3346 const char *keys)
3347{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003348 struct audio_device *adev = (struct audio_device *)dev;
3349 struct str_parms *reply = str_parms_create();
3350 struct str_parms *query = str_parms_create_str(keys);
3351 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303352 char value[256] = {0};
3353 int ret = 0;
3354
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003355 if (!query || !reply) {
3356 ALOGE("adev_get_parameters: failed to create query or reply");
3357 return NULL;
3358 }
3359
Naresh Tannirud7205b62014-06-20 02:54:48 +05303360 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3361 sizeof(value));
3362 if (ret >=0) {
3363 int val = 1;
3364 pthread_mutex_lock(&adev->snd_card_status.lock);
3365 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3366 val = 0;
3367 pthread_mutex_unlock(&adev->snd_card_status.lock);
3368 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3369 goto exit;
3370 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003371
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003372 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003373 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003374 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003375 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303376 pthread_mutex_unlock(&adev->lock);
3377
Naresh Tannirud7205b62014-06-20 02:54:48 +05303378exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003379 str = str_parms_to_str(reply);
3380 str_parms_destroy(query);
3381 str_parms_destroy(reply);
3382
3383 ALOGV("%s: exit: returns - %s", __func__, str);
3384 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385}
3386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003387static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388{
3389 return 0;
3390}
3391
3392static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3393{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003394 int ret;
3395 struct audio_device *adev = (struct audio_device *)dev;
3396 pthread_mutex_lock(&adev->lock);
3397 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003398 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003399 pthread_mutex_unlock(&adev->lock);
3400 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401}
3402
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003403static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3404 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405{
3406 return -ENOSYS;
3407}
3408
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003409static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3410 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411{
3412 return -ENOSYS;
3413}
3414
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003415static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3416 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417{
3418 return -ENOSYS;
3419}
3420
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003421static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3422 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423{
3424 return -ENOSYS;
3425}
3426
3427static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3428{
3429 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 pthread_mutex_lock(&adev->lock);
3432 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003433 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003435 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3436 voice_is_in_call(adev)) {
3437 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003438 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003439 adev->current_call_output = NULL;
3440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 }
3442 pthread_mutex_unlock(&adev->lock);
3443 return 0;
3444}
3445
3446static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3447{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003448 int ret;
3449
3450 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003451 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003452 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3453 pthread_mutex_unlock(&adev->lock);
3454
3455 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456}
3457
3458static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3459{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003460 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 return 0;
3462}
3463
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003464static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 const struct audio_config *config)
3466{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003467 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003469 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3470 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471}
3472
3473static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003474 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 audio_devices_t devices,
3476 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003477 struct audio_stream_in **stream_in,
3478 audio_input_flags_t flags __unused,
3479 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003480 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481{
3482 struct audio_device *adev = (struct audio_device *)dev;
3483 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003484 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003485 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003486 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 *stream_in = NULL;
3489 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3490 return -EINVAL;
3491
3492 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003493
3494 if (!in) {
3495 ALOGE("failed to allocate input stream");
3496 return -ENOMEM;
3497 }
3498
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303499 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003500 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3501 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003503 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 in->stream.common.get_sample_rate = in_get_sample_rate;
3506 in->stream.common.set_sample_rate = in_set_sample_rate;
3507 in->stream.common.get_buffer_size = in_get_buffer_size;
3508 in->stream.common.get_channels = in_get_channels;
3509 in->stream.common.get_format = in_get_format;
3510 in->stream.common.set_format = in_set_format;
3511 in->stream.common.standby = in_standby;
3512 in->stream.common.dump = in_dump;
3513 in->stream.common.set_parameters = in_set_parameters;
3514 in->stream.common.get_parameters = in_get_parameters;
3515 in->stream.common.add_audio_effect = in_add_audio_effect;
3516 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3517 in->stream.set_gain = in_set_gain;
3518 in->stream.read = in_read;
3519 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3520
3521 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003522 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 in->standby = 1;
3525 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003526 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003527 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
3529 /* Update config params with the requested sample rate and channels */
3530 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003531 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3532 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3533 is_low_latency = true;
3534#if LOW_LATENCY_CAPTURE_USE_CASE
3535 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3536#endif
3537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003542 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303543 if (adev->mode != AUDIO_MODE_IN_CALL) {
3544 ret = -EINVAL;
3545 goto err_open;
3546 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003547 if (config->sample_rate == 0)
3548 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3549 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3550 config->sample_rate != 8000) {
3551 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3552 ret = -EINVAL;
3553 goto err_open;
3554 }
3555 if (config->format == AUDIO_FORMAT_DEFAULT)
3556 config->format = AUDIO_FORMAT_PCM_16_BIT;
3557 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3558 config->format = AUDIO_FORMAT_PCM_16_BIT;
3559 ret = -EINVAL;
3560 goto err_open;
3561 }
3562
3563 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3564 in->config = pcm_config_afe_proxy_record;
3565 in->config.channels = channel_count;
3566 in->config.rate = config->sample_rate;
3567 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003568 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003569 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003570 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3571 ret = -EINVAL;
3572 goto err_open;
3573 }
3574 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003575 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003576 }
Mingming Yine62d7842013-10-25 16:26:03 -07003577 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003578 audio_extn_compr_cap_format_supported(config->format) &&
3579 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003580 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003581 } else {
3582 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003583 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003584 buffer_size = get_input_buffer_size(config->sample_rate,
3585 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003586 channel_count,
3587 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003588 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003589 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3590 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3591 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3592 (in->config.rate == 8000 || in->config.rate == 16000) &&
3593 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3594 voice_extn_compress_voip_open_input_stream(in);
3595 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003596 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003598 /* This stream could be for sound trigger lab,
3599 get sound trigger pcm if present */
3600 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303601 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003604 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003605 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606
3607err_open:
3608 free(in);
3609 *stream_in = NULL;
3610 return ret;
3611}
3612
3613static void adev_close_input_stream(struct audio_hw_device *dev,
3614 struct audio_stream_in *stream)
3615{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003616 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003617 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003618 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303619
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303620 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003621
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303622 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003623 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303624
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003625 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303626 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003627 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303628 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003629 if (ret != 0)
3630 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3631 __func__, ret);
3632 } else
3633 in_standby(&stream->common);
3634
Mingming Yin7b762e72015-03-04 13:47:32 -08003635 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003636 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003637 audio_extn_ssr_deinit();
3638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639
Mingming Yine62d7842013-10-25 16:26:03 -07003640 if(audio_extn_compr_cap_enabled() &&
3641 audio_extn_compr_cap_format_supported(in->config.format))
3642 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003643
3644 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 return;
3646}
3647
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003648static int adev_dump(const audio_hw_device_t *device __unused,
3649 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650{
3651 return 0;
3652}
3653
3654static int adev_close(hw_device_t *device)
3655{
3656 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003657
3658 if (!adev)
3659 return 0;
3660
3661 pthread_mutex_lock(&adev_init_lock);
3662
3663 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003664 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003665 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003666 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003667 audio_route_free(adev->audio_route);
3668 free(adev->snd_dev_ref_cnt);
3669 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003670 if (adev->adm_deinit)
3671 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003672 free(device);
3673 adev = NULL;
3674 }
3675 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 return 0;
3678}
3679
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003680/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3681 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3682 * just that it _might_ work.
3683 */
3684static int period_size_is_plausible_for_low_latency(int period_size)
3685{
3686 switch (period_size) {
3687 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003688 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003689 case 240:
3690 case 320:
3691 case 480:
3692 return 1;
3693 default:
3694 return 0;
3695 }
3696}
3697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698static int adev_open(const hw_module_t *module, const char *name,
3699 hw_device_t **device)
3700{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003701 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003703 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3705
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003706 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003707 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003708 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003709 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003710 ALOGD("%s: returning existing instance of adev", __func__);
3711 ALOGD("%s: exit", __func__);
3712 pthread_mutex_unlock(&adev_init_lock);
3713 return 0;
3714 }
3715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 adev = calloc(1, sizeof(struct audio_device));
3717
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003718 if (!adev) {
3719 pthread_mutex_unlock(&adev_init_lock);
3720 return -ENOMEM;
3721 }
3722
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003723 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3726 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3727 adev->device.common.module = (struct hw_module_t *)module;
3728 adev->device.common.close = adev_close;
3729
3730 adev->device.init_check = adev_init_check;
3731 adev->device.set_voice_volume = adev_set_voice_volume;
3732 adev->device.set_master_volume = adev_set_master_volume;
3733 adev->device.get_master_volume = adev_get_master_volume;
3734 adev->device.set_master_mute = adev_set_master_mute;
3735 adev->device.get_master_mute = adev_get_master_mute;
3736 adev->device.set_mode = adev_set_mode;
3737 adev->device.set_mic_mute = adev_set_mic_mute;
3738 adev->device.get_mic_mute = adev_get_mic_mute;
3739 adev->device.set_parameters = adev_set_parameters;
3740 adev->device.get_parameters = adev_get_parameters;
3741 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3742 adev->device.open_output_stream = adev_open_output_stream;
3743 adev->device.close_output_stream = adev_close_output_stream;
3744 adev->device.open_input_stream = adev_open_input_stream;
3745 adev->device.close_input_stream = adev_close_input_stream;
3746 adev->device.dump = adev_dump;
3747
3748 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003750 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003751 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003754 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003755 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003756 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003757 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003758 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003759 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003760 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303761
3762 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3763 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003765 adev->platform = platform_init(adev);
3766 if (!adev->platform) {
3767 free(adev->snd_dev_ref_cnt);
3768 free(adev);
3769 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3770 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003771 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003772 return -EINVAL;
3773 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003774
Naresh Tanniru4c630392014-05-12 01:05:52 +05303775 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3776
Eric Laurentc4aef752013-09-12 17:45:53 -07003777 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3778 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3779 if (adev->visualizer_lib == NULL) {
3780 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3781 } else {
3782 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3783 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003784 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003785 "visualizer_hal_start_output");
3786 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003787 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003788 "visualizer_hal_stop_output");
3789 }
3790 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003791 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003792 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003793
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003794 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3795 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3796 if (adev->offload_effects_lib == NULL) {
3797 ALOGE("%s: DLOPEN failed for %s", __func__,
3798 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3799 } else {
3800 ALOGV("%s: DLOPEN successful for %s", __func__,
3801 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3802 adev->offload_effects_start_output =
3803 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3804 "offload_effects_bundle_hal_start_output");
3805 adev->offload_effects_stop_output =
3806 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3807 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003808 adev->offload_effects_set_hpx_state =
3809 (int (*)(bool))dlsym(adev->offload_effects_lib,
3810 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303811 adev->offload_effects_get_parameters =
3812 (void (*)(struct str_parms *, struct str_parms *))
3813 dlsym(adev->offload_effects_lib,
3814 "offload_effects_bundle_get_parameters");
3815 adev->offload_effects_set_parameters =
3816 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3817 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003818 }
3819 }
3820
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003821 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3822 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3823 if (adev->adm_lib == NULL) {
3824 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3825 } else {
3826 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3827 adev->adm_init = (adm_init_t)
3828 dlsym(adev->adm_lib, "adm_init");
3829 adev->adm_deinit = (adm_deinit_t)
3830 dlsym(adev->adm_lib, "adm_deinit");
3831 adev->adm_register_input_stream = (adm_register_input_stream_t)
3832 dlsym(adev->adm_lib, "adm_register_input_stream");
3833 adev->adm_register_output_stream = (adm_register_output_stream_t)
3834 dlsym(adev->adm_lib, "adm_register_output_stream");
3835 adev->adm_deregister_stream = (adm_deregister_stream_t)
3836 dlsym(adev->adm_lib, "adm_deregister_stream");
3837 adev->adm_request_focus = (adm_request_focus_t)
3838 dlsym(adev->adm_lib, "adm_request_focus");
3839 adev->adm_abandon_focus = (adm_abandon_focus_t)
3840 dlsym(adev->adm_lib, "adm_abandon_focus");
3841 }
3842 }
3843
Mingming Yin514a8bc2014-07-29 15:22:21 -07003844 adev->bt_wb_speech_enabled = false;
3845
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003846 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003847 *device = &adev->device.common;
3848
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003849 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3850 &adev->streams_output_cfg_list);
3851
Kiran Kandi910e1862013-10-29 13:29:42 -07003852 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003853
3854 char value[PROPERTY_VALUE_MAX];
3855 int trial;
3856 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3857 trial = atoi(value);
3858 if (period_size_is_plausible_for_low_latency(trial)) {
3859 pcm_config_low_latency.period_size = trial;
3860 pcm_config_low_latency.start_threshold = trial / 4;
3861 pcm_config_low_latency.avail_min = trial / 4;
3862 configured_low_latency_capture_period_size = trial;
3863 }
3864 }
3865 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3866 trial = atoi(value);
3867 if (period_size_is_plausible_for_low_latency(trial)) {
3868 configured_low_latency_capture_period_size = trial;
3869 }
3870 }
3871
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003872 pthread_mutex_unlock(&adev_init_lock);
3873
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003874 if (adev->adm_init)
3875 adev->adm_data = adev->adm_init();
3876
Eric Laurent994a6932013-07-17 11:51:42 -07003877 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 return 0;
3879}
3880
3881static struct hw_module_methods_t hal_module_methods = {
3882 .open = adev_open,
3883};
3884
3885struct audio_module HAL_MODULE_INFO_SYM = {
3886 .common = {
3887 .tag = HARDWARE_MODULE_TAG,
3888 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3889 .hal_api_version = HARDWARE_HAL_API_VERSION,
3890 .id = AUDIO_HARDWARE_MODULE_ID,
3891 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003892 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893 .methods = &hal_module_methods,
3894 },
3895};