blob: de645bdeddf1d81ff8462ae15905d0f3fd38e504 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -0700180 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
215#ifdef MULTIPLE_OFFLOAD_ENABLED
216 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
224#endif
225};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226
227#define STRING_TO_ENUM(string) { #string, string }
228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229struct string_to_enum {
230 const char *name;
231 uint32_t value;
232};
233
234static const struct string_to_enum out_channels_name_to_enum_table[] = {
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
242};
243
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700244static const struct string_to_enum out_formats_name_to_enum_table[] = {
245 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
247 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
248};
249
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700250static struct audio_device *adev = NULL;
251static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700252static unsigned int audio_device_ref_count;
253
Haynes Mathew George5191a852013-09-11 14:19:36 -0700254static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800256static int check_and_set_gapless_mode(struct audio_device *adev) {
257
258
259 char value[PROPERTY_VALUE_MAX] = {0};
260 bool gapless_enabled = false;
261 const char *mixer_ctl_name = "Compress Gapless Playback";
262 struct mixer_ctl *ctl;
263
264 ALOGV("%s:", __func__);
265 property_get("audio.offload.gapless.enabled", value, NULL);
266 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
267
268 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
269 if (!ctl) {
270 ALOGE("%s: Could not get ctl for mixer cmd - %s",
271 __func__, mixer_ctl_name);
272 return -EINVAL;
273 }
274
275 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
276 ALOGE("%s: Could not set gapless mode %d",
277 __func__, gapless_enabled);
278 return -EINVAL;
279 }
280 return 0;
281}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700282
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700283static bool is_supported_format(audio_format_t format)
284{
Eric Laurent86e17132013-09-12 17:49:30 -0700285 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530286 format == AUDIO_FORMAT_AAC_LC ||
287 format == AUDIO_FORMAT_AAC_HE_V1 ||
288 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangan93672f12015-08-24 20:30:31 +0530289 format == AUDIO_FORMAT_AAC_ADTS_LC ||
290 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
291 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800292 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700293 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530295 format == AUDIO_FORMAT_ALAC ||
296 format == AUDIO_FORMAT_APE ||
297 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800298 format == AUDIO_FORMAT_WMA ||
299 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800300 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301
302 return false;
303}
304
305static int get_snd_codec_id(audio_format_t format)
306{
307 int id = 0;
308
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700310 case AUDIO_FORMAT_MP3:
311 id = SND_AUDIOCODEC_MP3;
312 break;
313 case AUDIO_FORMAT_AAC:
314 id = SND_AUDIOCODEC_AAC;
315 break;
Manish Dewangan93672f12015-08-24 20:30:31 +0530316 case AUDIO_FORMAT_AAC_ADTS:
317 id = SND_AUDIOCODEC_AAC;
318 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530319 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800320 id = SND_AUDIOCODEC_PCM;
321 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700322 case AUDIO_FORMAT_FLAC:
323 id = SND_AUDIOCODEC_FLAC;
324 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530325 case AUDIO_FORMAT_ALAC:
326 id = SND_AUDIOCODEC_ALAC;
327 break;
328 case AUDIO_FORMAT_APE:
329 id = SND_AUDIOCODEC_APE;
330 break;
331 case AUDIO_FORMAT_VORBIS:
332 id = SND_AUDIOCODEC_VORBIS;
333 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800334 case AUDIO_FORMAT_WMA:
335 id = SND_AUDIOCODEC_WMA;
336 break;
337 case AUDIO_FORMAT_WMA_PRO:
338 id = SND_AUDIOCODEC_WMA_PRO;
339 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700340 default:
Mingming Yin90310102013-11-13 16:57:00 -0800341 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700342 }
343
344 return id;
345}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800346
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530347int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530348{
349 int snd_scard_state;
350
351 if (!adev)
352 return SND_CARD_STATE_OFFLINE;
353
354 pthread_mutex_lock(&adev->snd_card_status.lock);
355 snd_scard_state = adev->snd_card_status.state;
356 pthread_mutex_unlock(&adev->snd_card_status.lock);
357
358 return snd_scard_state;
359}
360
361static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
362{
363 if (!adev)
364 return -ENOSYS;
365
366 pthread_mutex_lock(&adev->snd_card_status.lock);
367 adev->snd_card_status.state = snd_scard_state;
368 pthread_mutex_unlock(&adev->snd_card_status.lock);
369
370 return 0;
371}
372
Avinash Vaish71a8b972014-07-24 15:36:33 +0530373static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
374 struct audio_usecase *uc_info)
375{
376 struct listnode *node;
377 struct audio_usecase *usecase;
378
379 if (uc_info == NULL)
380 return -EINVAL;
381
382 /* Re-route all voice usecases on the shared backend other than the
383 specified usecase to new snd devices */
384 list_for_each(node, &adev->usecase_list) {
385 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800386 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530387 enable_audio_route(adev, usecase);
388 }
389 return 0;
390}
391
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700392int pcm_ioctl(struct pcm *pcm, int request, ...)
393{
394 va_list ap;
395 void * arg;
396 int pcm_fd = *(int*)pcm;
397
398 va_start(ap, request);
399 arg = va_arg(ap, void *);
400 va_end(ap);
401
402 return ioctl(pcm_fd, request, arg);
403}
404
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700405int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700406 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800407{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700408 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700409 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800410
411 if (usecase == NULL)
412 return -EINVAL;
413
414 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
415
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800416 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700417 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800418 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700419 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800420
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800421#ifdef DS1_DOLBY_DAP_ENABLED
422 audio_extn_dolby_set_dmid(adev);
423 audio_extn_dolby_set_endpoint(adev);
424#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700425 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700426 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530427 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700428 audio_extn_utils_send_app_type_cfg(usecase);
Dhananjay Kumarcb419212015-08-28 13:24:16 +0530429 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800430 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530431 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700432 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
433 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434 ALOGV("%s: exit", __func__);
435 return 0;
436}
437
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700438int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700439 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800440{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700442 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530444 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 return -EINVAL;
446
447 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700448 if (usecase->type == PCM_CAPTURE)
449 snd_device = usecase->in_snd_device;
450 else
451 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800452 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530453 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700454 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
455 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700456 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530457 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458 ALOGV("%s: exit", __func__);
459 return 0;
460}
461
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700462int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700463 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800464{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700465 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
466
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800467 if (snd_device < SND_DEVICE_MIN ||
468 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800469 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472
473 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474
475 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
476 ALOGE("%s: Invalid sound device returned", __func__);
477 return -EINVAL;
478 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700479 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700480 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700481 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700482 return 0;
483 }
484
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700485 if (audio_extn_spkr_prot_is_enabled())
486 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700487 /* start usb playback thread */
488 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
489 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
490 audio_extn_usb_start_playback(adev);
491
492 /* start usb capture thread */
493 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
494 audio_extn_usb_start_capture(adev);
495
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530496 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530497 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700499 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700500 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
501 adev->snd_dev_ref_cnt[snd_device]--;
502 return -EINVAL;
503 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200504 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800505 if (audio_extn_spkr_prot_start_processing(snd_device)) {
506 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200507 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800508 return -EINVAL;
509 }
510 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700511 ALOGV("%s: snd_device(%d: %s)", __func__,
512 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700513 /* due to the possibility of calibration overwrite between listen
514 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700515 audio_extn_sound_trigger_update_device_status(snd_device,
516 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530517 audio_extn_listen_update_device_status(snd_device,
518 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700519 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700520 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700521 audio_extn_sound_trigger_update_device_status(snd_device,
522 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530523 audio_extn_listen_update_device_status(snd_device,
524 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700525 return -EINVAL;
526 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300527 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700528 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800530 return 0;
531}
532
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700533int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700534 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700536 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
537
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800538 if (snd_device < SND_DEVICE_MIN ||
539 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800540 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800541 return -EINVAL;
542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700543 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
544 ALOGE("%s: device ref cnt is already 0", __func__);
545 return -EINVAL;
546 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700549
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
551 ALOGE("%s: Invalid sound device returned", __func__);
552 return -EINVAL;
553 }
554
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700555 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700556 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700557 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558 /* exit usb play back thread */
559 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
560 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
561 audio_extn_usb_stop_playback();
562
563 /* exit usb capture thread */
564 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700565 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800566
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530567 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530568 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800569 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700570 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700571 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300572 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700573 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300574 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700575
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530576 if (snd_device == SND_DEVICE_OUT_HDMI)
577 adev->mChannelStatusSet = false;
578
Linux Build Service Account75e43952015-08-26 19:58:56 -0700579 if (snd_device == SND_DEVICE_OUT_HDMI)
580 adev->mChannelStatusSet = false;
581
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200582 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700583 audio_extn_sound_trigger_update_device_status(snd_device,
584 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530585 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800586 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800589 return 0;
590}
591
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592static void check_usecases_codec_backend(struct audio_device *adev,
593 struct audio_usecase *uc_info,
594 snd_device_t snd_device)
595{
596 struct listnode *node;
597 struct audio_usecase *usecase;
598 bool switch_device[AUDIO_USECASE_MAX];
599 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530600 int backend_idx = DEFAULT_CODEC_BACKEND;
601 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700602
603 /*
604 * This function is to make sure that all the usecases that are active on
605 * the hardware codec backend are always routed to any one device that is
606 * handled by the hardware codec.
607 * For example, if low-latency and deep-buffer usecases are currently active
608 * on speaker and out_set_parameters(headset) is received on low-latency
609 * output, then we have to make sure deep-buffer is also switched to headset,
610 * because of the limitation that both the devices cannot be enabled
611 * at the same time as they share the same backend.
612 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700613 /*
614 * This call is to check if we need to force routing for a particular stream
615 * If there is a backend configuration change for the device when a
616 * new stream starts, then ADM needs to be closed and re-opened with the new
617 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530618 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700619 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530620 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
621 snd_device);
622 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800624 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800625 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 for (i = 0; i < AUDIO_USECASE_MAX; i++)
627 switch_device[i] = false;
628
629 list_for_each(node, &adev->usecase_list) {
630 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530631
632 if (usecase == uc_info)
633 continue;
634 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
635 ALOGV("%s: backend_idx: %d,"
636 "usecase_backend_idx: %d, curr device: %s, usecase device:"
637 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530638 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530639
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800640 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700641 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530642 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
643 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530644 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530645 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700646 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700647 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 switch_device[usecase->id] = true;
649 num_uc_to_switch++;
650 }
651 }
652
653 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700654 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530656 /* Make sure the previous devices to be disabled first and then enable the
657 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 }
663 }
664
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
667 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700668 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700669 }
670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 /* Re-route all the usecases on the shared backend other than the
673 specified usecase to new snd devices */
674 list_for_each(node, &adev->usecase_list) {
675 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530676 /* Update the out_snd_device only before enabling the audio route */
677 if (switch_device[usecase->id] ) {
678 usecase->out_snd_device = snd_device;
679 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530680 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 }
682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 }
684}
685
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700686static void check_and_route_capture_usecases(struct audio_device *adev,
687 struct audio_usecase *uc_info,
688 snd_device_t snd_device)
689{
690 struct listnode *node;
691 struct audio_usecase *usecase;
692 bool switch_device[AUDIO_USECASE_MAX];
693 int i, num_uc_to_switch = 0;
694
695 /*
696 * This function is to make sure that all the active capture usecases
697 * are always routed to the same input sound device.
698 * For example, if audio-record and voice-call usecases are currently
699 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
700 * is received for voice call then we have to make sure that audio-record
701 * usecase is also switched to earpiece i.e. voice-dmic-ef,
702 * because of the limitation that two devices cannot be enabled
703 * at the same time if they share the same backend.
704 */
705 for (i = 0; i < AUDIO_USECASE_MAX; i++)
706 switch_device[i] = false;
707
708 list_for_each(node, &adev->usecase_list) {
709 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800710 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700712 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700713 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530714 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
715 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700716 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700717 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
718 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700719 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700720 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700721 switch_device[usecase->id] = true;
722 num_uc_to_switch++;
723 }
724 }
725
726 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700727 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530729 /* Make sure the previous devices to be disabled first and then enable the
730 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731 list_for_each(node, &adev->usecase_list) {
732 usecase = node_to_item(node, struct audio_usecase, list);
733 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700734 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800735 }
736 }
737
738 list_for_each(node, &adev->usecase_list) {
739 usecase = node_to_item(node, struct audio_usecase, list);
740 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700741 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 }
743 }
744
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745 /* Re-route all the usecases on the shared backend other than the
746 specified usecase to new snd devices */
747 list_for_each(node, &adev->usecase_list) {
748 usecase = node_to_item(node, struct audio_usecase, list);
749 /* Update the in_snd_device only before enabling the audio route */
750 if (switch_device[usecase->id] ) {
751 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800752 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530753 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 }
755 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 }
757}
758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800759/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700760static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800761{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700763 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800764
765 switch (channels) {
766 /*
767 * Do not handle stereo output in Multi-channel cases
768 * Stereo case is handled in normal playback path
769 */
770 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700771 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
774 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
776 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777 break;
778 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700779 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
782 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800786 break;
787 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700788 ALOGE("HDMI does not support multi channel playback");
789 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800790 break;
791 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700792 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793}
794
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800795audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
796 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700797{
798 struct audio_usecase *usecase;
799 struct listnode *node;
800
801 list_for_each(node, &adev->usecase_list) {
802 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800803 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700804 ALOGV("%s: usecase id %d", __func__, usecase->id);
805 return usecase->id;
806 }
807 }
808 return USECASE_INVALID;
809}
810
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700811struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700812 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700813{
814 struct audio_usecase *usecase;
815 struct listnode *node;
816
817 list_for_each(node, &adev->usecase_list) {
818 usecase = node_to_item(node, struct audio_usecase, list);
819 if (usecase->id == uc_id)
820 return usecase;
821 }
822 return NULL;
823}
824
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700825int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800827 snd_device_t out_snd_device = SND_DEVICE_NONE;
828 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829 struct audio_usecase *usecase = NULL;
830 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800831 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800832 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800833 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800834 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 usecase = get_usecase_from_list(adev, uc_id);
838 if (usecase == NULL) {
839 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
840 return -EINVAL;
841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800843 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800844 (usecase->type == VOIP_CALL) ||
845 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700846 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800847 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700848 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 usecase->devices = usecase->stream.out->devices;
850 } else {
851 /*
852 * If the voice call is active, use the sound devices of voice call usecase
853 * so that it would not result any device switch. All the usecases will
854 * be switched to new device when select_devices() is called for voice call
855 * usecase. This is to avoid switching devices for voice call when
856 * check_usecases_codec_backend() is called below.
857 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700858 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700859 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800860 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700861 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
862 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 in_snd_device = vc_usecase->in_snd_device;
864 out_snd_device = vc_usecase->out_snd_device;
865 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800866 } else if (voice_extn_compress_voip_is_active(adev)) {
867 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700868 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530869 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700870 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800871 in_snd_device = voip_usecase->in_snd_device;
872 out_snd_device = voip_usecase->out_snd_device;
873 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800874 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800875 hfp_ucid = audio_extn_hfp_get_usecase();
876 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700877 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800878 in_snd_device = hfp_usecase->in_snd_device;
879 out_snd_device = hfp_usecase->out_snd_device;
880 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 if (usecase->type == PCM_PLAYBACK) {
883 usecase->devices = usecase->stream.out->devices;
884 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700885 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700886 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800887 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700888 if (usecase->stream.out == adev->primary_output &&
889 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800890 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 select_devices(adev, adev->active_input->usecase);
892 }
893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 } else if (usecase->type == PCM_CAPTURE) {
895 usecase->devices = usecase->stream.in->device;
896 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700898 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530899 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
900 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
901 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
902 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700903 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -0700904 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700905 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
906 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700907 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700908 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 }
911 }
912
913 if (out_snd_device == usecase->out_snd_device &&
914 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915 return 0;
916 }
917
sangwoobc677242013-08-08 16:53:43 +0900918 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700919 out_snd_device, platform_get_snd_device_name(out_snd_device),
920 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922 /*
923 * Limitation: While in call, to do a device switch we need to disable
924 * and enable both RX and TX devices though one of them is same as current
925 * device.
926 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700927 if ((usecase->type == VOICE_CALL) &&
928 (usecase->in_snd_device != SND_DEVICE_NONE) &&
929 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700930 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700931 }
932
933 if (((usecase->type == VOICE_CALL) ||
934 (usecase->type == VOIP_CALL)) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
936 /* Disable sidetone only if voice/voip call already exists */
937 if (voice_is_call_state_active(adev) ||
938 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700939 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800940 }
941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 /* Disable current sound devices */
943 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700944 disable_audio_route(adev, usecase);
945 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946 }
947
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 disable_audio_route(adev, usecase);
950 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951 }
952
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800953 /* Applicable only on the targets that has external modem.
954 * New device information should be sent to modem before enabling
955 * the devices to reduce in-call device switch time.
956 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700957 if ((usecase->type == VOICE_CALL) &&
958 (usecase->in_snd_device != SND_DEVICE_NONE) &&
959 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800960 status = platform_switch_voice_call_enable_device_config(adev->platform,
961 out_snd_device,
962 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700963 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800964
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700965 /* Enable new sound devices */
966 if (out_snd_device != SND_DEVICE_NONE) {
967 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
968 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970 }
971
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700972 if (in_snd_device != SND_DEVICE_NONE) {
973 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700974 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976
Avinash Vaish71a8b972014-07-24 15:36:33 +0530977 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700978 status = platform_switch_voice_call_device_post(adev->platform,
979 out_snd_device,
980 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530981 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700982 /* Enable sidetone only if voice/voip call already exists */
983 if (voice_is_call_state_active(adev) ||
984 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700985 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530986 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800987
sangwoo170731f2013-06-08 15:36:36 +0900988 usecase->in_snd_device = in_snd_device;
989 usecase->out_snd_device = out_snd_device;
990
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530991 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700992 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530993 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700994 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530995 usecase->stream.out->flags,
996 usecase->stream.out->format,
997 usecase->stream.out->sample_rate,
998 usecase->stream.out->bit_width,
999 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001000 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301001 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001002
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001003 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001004
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001005 /* Applicable only on the targets that has external modem.
1006 * Enable device command should be sent to modem only after
1007 * enabling voice call mixer controls
1008 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001009 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001010 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1011 out_snd_device,
1012 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301013 ALOGD("%s: done",__func__);
1014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 return status;
1016}
1017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018static int stop_input_stream(struct stream_in *in)
1019{
1020 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 struct audio_usecase *uc_info;
1022 struct audio_device *adev = in->dev;
1023
Eric Laurentc8400632013-02-14 19:04:54 -08001024 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Eric Laurent994a6932013-07-17 11:51:42 -07001026 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 uc_info = get_usecase_from_list(adev, in->usecase);
1029 if (uc_info == NULL) {
1030 ALOGE("%s: Could not find the usecase (%d) in the list",
1031 __func__, in->usecase);
1032 return -EINVAL;
1033 }
1034
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001035 /* Close in-call recording streams */
1036 voice_check_and_stop_incall_rec_usecase(adev, in);
1037
Eric Laurent150dbfe2013-02-27 14:31:02 -08001038 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001039 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040
1041 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001044 list_remove(&uc_info->list);
1045 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Eric Laurent994a6932013-07-17 11:51:42 -07001047 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048 return ret;
1049}
1050
1051int start_input_stream(struct stream_in *in)
1052{
1053 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001054 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 struct audio_usecase *uc_info;
1056 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301057 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301059 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1060 if (get_usecase_from_list(adev, usecase) == NULL)
1061 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301062 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1063 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001064
Naresh Tanniru80659832014-06-04 18:17:56 +05301065
1066 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301067 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301068 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301069 goto error_config;
1070 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301071
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001072 /* Check if source matches incall recording usecase criteria */
1073 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1074 if (ret)
1075 goto error_config;
1076 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301077 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1078
1079 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1080 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1081 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1082 goto error_config;
1083 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001084
Eric Laurentb23d5282013-05-14 15:27:20 -07001085 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 if (in->pcm_device_id < 0) {
1087 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1088 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001089 ret = -EINVAL;
1090 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092
1093 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001095
1096 if (!uc_info) {
1097 ret = -ENOMEM;
1098 goto error_config;
1099 }
1100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 uc_info->id = in->usecase;
1102 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001103 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104 uc_info->devices = in->device;
1105 uc_info->in_snd_device = SND_DEVICE_NONE;
1106 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001108 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301109 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111
Eric Laurentc8400632013-02-14 19:04:54 -08001112 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001113 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1114
1115 unsigned int flags = PCM_IN;
1116 unsigned int pcm_open_retry_count = 0;
1117
1118 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1119 flags |= PCM_MMAP | PCM_NOIRQ;
1120 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1121 }
1122
1123 while (1) {
1124 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1125 flags, &in->config);
1126 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1127 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1128 if (in->pcm != NULL) {
1129 pcm_close(in->pcm);
1130 in->pcm = NULL;
1131 }
1132 if (pcm_open_retry_count-- == 0) {
1133 ret = -EIO;
1134 goto error_open;
1135 }
1136 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1137 continue;
1138 }
1139 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301141 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301142
Naresh Tanniru4a080142015-06-15 10:35:19 -07001143 ALOGV("%s: pcm_prepare start", __func__);
1144 pcm_prepare(in->pcm);
Eric Laurent994a6932013-07-17 11:51:42 -07001145 ALOGV("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001146
Eric Laurentc8400632013-02-14 19:04:54 -08001147 return ret;
1148
1149error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301151 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001152
1153error_config:
1154 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001155 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001156
1157 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158}
1159
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001160void lock_input_stream(struct stream_in *in)
1161{
1162 pthread_mutex_lock(&in->pre_lock);
1163 pthread_mutex_lock(&in->lock);
1164 pthread_mutex_unlock(&in->pre_lock);
1165}
1166
1167void lock_output_stream(struct stream_out *out)
1168{
1169 pthread_mutex_lock(&out->pre_lock);
1170 pthread_mutex_lock(&out->lock);
1171 pthread_mutex_unlock(&out->pre_lock);
1172}
1173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001174/* must be called with out->lock locked */
1175static int send_offload_cmd_l(struct stream_out* out, int command)
1176{
1177 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1178
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001179 if (!cmd) {
1180 ALOGE("failed to allocate mem for command 0x%x", command);
1181 return -ENOMEM;
1182 }
1183
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001184 ALOGVV("%s %d", __func__, command);
1185
1186 cmd->cmd = command;
1187 list_add_tail(&out->offload_cmd_list, &cmd->node);
1188 pthread_cond_signal(&out->offload_cond);
1189 return 0;
1190}
1191
1192/* must be called iwth out->lock locked */
1193static void stop_compressed_output_l(struct stream_out *out)
1194{
1195 out->offload_state = OFFLOAD_STATE_IDLE;
1196 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001197 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001198 if (out->compr != NULL) {
1199 compress_stop(out->compr);
1200 while (out->offload_thread_blocked) {
1201 pthread_cond_wait(&out->cond, &out->lock);
1202 }
1203 }
1204}
1205
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001206bool is_offload_usecase(audio_usecase_t uc_id)
1207{
1208 unsigned int i;
1209 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1210 if (uc_id == offload_usecases[i])
1211 return true;
1212 }
1213 return false;
1214}
1215
1216static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1217{
1218 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1219 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1220 char value[PROPERTY_VALUE_MAX] = {0};
1221
1222 property_get("audio.offload.multiple.enabled", value, NULL);
1223 if (!(atoi(value) || !strncmp("true", value, 4)))
1224 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1225
1226 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1227 for (i = 0; i < num_usecase; i++) {
1228 if (!(adev->offload_usecases_state & (0x1<<i))) {
1229 adev->offload_usecases_state |= 0x1 << i;
1230 ret = offload_usecases[i];
1231 break;
1232 }
1233 }
1234 ALOGV("%s: offload usecase is %d", __func__, ret);
1235 return ret;
1236}
1237
1238static void free_offload_usecase(struct audio_device *adev,
1239 audio_usecase_t uc_id)
1240{
1241 unsigned int i;
1242 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1243 if (offload_usecases[i] == uc_id) {
1244 adev->offload_usecases_state &= ~(0x1<<i);
1245 break;
1246 }
1247 }
1248 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1249}
1250
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001251static void *offload_thread_loop(void *context)
1252{
1253 struct stream_out *out = (struct stream_out *) context;
1254 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001255 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001256
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001257 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1258 set_sched_policy(0, SP_FOREGROUND);
1259 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1260
1261 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001262 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001263 for (;;) {
1264 struct offload_cmd *cmd = NULL;
1265 stream_callback_event_t event;
1266 bool send_callback = false;
1267
1268 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1269 __func__, list_empty(&out->offload_cmd_list),
1270 out->offload_state);
1271 if (list_empty(&out->offload_cmd_list)) {
1272 ALOGV("%s SLEEPING", __func__);
1273 pthread_cond_wait(&out->offload_cond, &out->lock);
1274 ALOGV("%s RUNNING", __func__);
1275 continue;
1276 }
1277
1278 item = list_head(&out->offload_cmd_list);
1279 cmd = node_to_item(item, struct offload_cmd, node);
1280 list_remove(item);
1281
1282 ALOGVV("%s STATE %d CMD %d out->compr %p",
1283 __func__, out->offload_state, cmd->cmd, out->compr);
1284
1285 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1286 free(cmd);
1287 break;
1288 }
1289
1290 if (out->compr == NULL) {
1291 ALOGE("%s: Compress handle is NULL", __func__);
1292 pthread_cond_signal(&out->cond);
1293 continue;
1294 }
1295 out->offload_thread_blocked = true;
1296 pthread_mutex_unlock(&out->lock);
1297 send_callback = false;
1298 switch(cmd->cmd) {
1299 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001300 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001302 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001303 send_callback = true;
1304 event = STREAM_CBK_EVENT_WRITE_READY;
1305 break;
1306 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001307 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301308 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001309 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301310 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001311 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301312 if (ret < 0)
1313 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301314 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301315 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001316 compress_drain(out->compr);
1317 else
1318 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301319 if (ret != -ENETRESET) {
1320 send_callback = true;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301321 pthread_mutex_lock(&out->lock);
1322 out->send_new_metadata = 1;
1323 out->send_next_track_params = true;
1324 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301325 event = STREAM_CBK_EVENT_DRAIN_READY;
1326 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1327 } else
1328 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 break;
1330 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001331 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001333 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001334 send_callback = true;
1335 event = STREAM_CBK_EVENT_DRAIN_READY;
1336 break;
1337 default:
1338 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1339 break;
1340 }
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001341 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001342 out->offload_thread_blocked = false;
1343 pthread_cond_signal(&out->cond);
vivek mehtacc70d4b2015-09-25 14:07:43 -07001344 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001345 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001346 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001347 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001348 free(cmd);
1349 }
1350
1351 pthread_cond_signal(&out->cond);
1352 while (!list_empty(&out->offload_cmd_list)) {
1353 item = list_head(&out->offload_cmd_list);
1354 list_remove(item);
1355 free(node_to_item(item, struct offload_cmd, node));
1356 }
1357 pthread_mutex_unlock(&out->lock);
1358
1359 return NULL;
1360}
1361
1362static int create_offload_callback_thread(struct stream_out *out)
1363{
1364 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1365 list_init(&out->offload_cmd_list);
1366 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1367 offload_thread_loop, out);
1368 return 0;
1369}
1370
1371static int destroy_offload_callback_thread(struct stream_out *out)
1372{
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001373 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001374 stop_compressed_output_l(out);
1375 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1376
1377 pthread_mutex_unlock(&out->lock);
1378 pthread_join(out->offload_thread, (void **) NULL);
1379 pthread_cond_destroy(&out->offload_cond);
1380
1381 return 0;
1382}
1383
Eric Laurent07eeafd2013-10-06 12:52:49 -07001384static bool allow_hdmi_channel_config(struct audio_device *adev)
1385{
1386 struct listnode *node;
1387 struct audio_usecase *usecase;
1388 bool ret = true;
1389
1390 list_for_each(node, &adev->usecase_list) {
1391 usecase = node_to_item(node, struct audio_usecase, list);
1392 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1393 /*
1394 * If voice call is already existing, do not proceed further to avoid
1395 * disabling/enabling both RX and TX devices, CSD calls, etc.
1396 * Once the voice call done, the HDMI channels can be configured to
1397 * max channels of remaining use cases.
1398 */
1399 if (usecase->id == USECASE_VOICE_CALL) {
1400 ALOGD("%s: voice call is active, no change in HDMI channels",
1401 __func__);
1402 ret = false;
1403 break;
1404 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1405 ALOGD("%s: multi channel playback is active, "
1406 "no change in HDMI channels", __func__);
1407 ret = false;
1408 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001409 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001410 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001411 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1412 ", no change in HDMI channels", __func__,
1413 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001414 ret = false;
1415 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 }
1417 }
1418 }
1419 return ret;
1420}
1421
1422static int check_and_set_hdmi_channels(struct audio_device *adev,
1423 unsigned int channels)
1424{
1425 struct listnode *node;
1426 struct audio_usecase *usecase;
1427
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001428 unsigned int supported_channels = platform_edid_get_max_channels(
1429 adev->platform);
1430 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 /* Check if change in HDMI channel config is allowed */
1432 if (!allow_hdmi_channel_config(adev))
1433 return 0;
1434
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001435 if (channels > supported_channels)
1436 channels = supported_channels;
1437
Eric Laurent07eeafd2013-10-06 12:52:49 -07001438 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001439 ALOGD("%s: Requested channels are same as current channels(%d)",
1440 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001441 return 0;
1442 }
1443
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001444 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001445 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001446 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001447 adev->cur_hdmi_channels = channels;
1448
1449 /*
1450 * Deroute all the playback streams routed to HDMI so that
1451 * the back end is deactivated. Note that backend will not
1452 * be deactivated if any one stream is connected to it.
1453 */
1454 list_for_each(node, &adev->usecase_list) {
1455 usecase = node_to_item(node, struct audio_usecase, list);
1456 if (usecase->type == PCM_PLAYBACK &&
1457 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001458 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001459 }
1460 }
1461
1462 /*
1463 * Enable all the streams disabled above. Now the HDMI backend
1464 * will be activated with new channel configuration
1465 */
1466 list_for_each(node, &adev->usecase_list) {
1467 usecase = node_to_item(node, struct audio_usecase, list);
1468 if (usecase->type == PCM_PLAYBACK &&
1469 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001470 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001471 }
1472 }
1473
1474 return 0;
1475}
1476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477static int stop_output_stream(struct stream_out *out)
1478{
1479 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 struct audio_usecase *uc_info;
1481 struct audio_device *adev = out->dev;
1482
Eric Laurent994a6932013-07-17 11:51:42 -07001483 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001484 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 uc_info = get_usecase_from_list(adev, out->usecase);
1486 if (uc_info == NULL) {
1487 ALOGE("%s: Could not find the usecase (%d) in the list",
1488 __func__, out->usecase);
1489 return -EINVAL;
1490 }
1491
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001492 if (is_offload_usecase(out->usecase) &&
1493 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001494 if (adev->visualizer_stop_output != NULL)
1495 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001496
1497 audio_extn_dts_remove_state_notifier_node(out->usecase);
1498
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001499 if (adev->offload_effects_stop_output != NULL)
1500 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1501 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001502
Eric Laurent150dbfe2013-02-27 14:31:02 -08001503 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001504 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505
1506 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001507 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001509 list_remove(&uc_info->list);
1510 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001512 if (is_offload_usecase(out->usecase) &&
1513 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1514 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1515 ALOGV("Disable passthrough , reset mixer to pcm");
1516 /* NO_PASSTHROUGH */
1517 out->compr_config.codec->compr_passthr = 0;
1518 audio_extn_dolby_set_hdmi_config(adev, out);
1519 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1520 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001521 /* Must be called after removing the usecase from list */
1522 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1523 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1524
Eric Laurent994a6932013-07-17 11:51:42 -07001525 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 return ret;
1527}
1528
1529int start_output_stream(struct stream_out *out)
1530{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001532 int sink_channels = 0;
1533 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 struct audio_usecase *uc_info;
1535 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301536 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001538 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1539 ret = -EINVAL;
1540 goto error_config;
1541 }
1542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301543 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1544 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1545 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301546
Naresh Tanniru80659832014-06-04 18:17:56 +05301547 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301548 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301549 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301550 goto error_config;
1551 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301552
Eric Laurentb23d5282013-05-14 15:27:20 -07001553 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 if (out->pcm_device_id < 0) {
1555 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1556 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001557 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001558 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 }
1560
1561 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001562
1563 if (!uc_info) {
1564 ret = -ENOMEM;
1565 goto error_config;
1566 }
1567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 uc_info->id = out->usecase;
1569 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001570 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001571 uc_info->devices = out->devices;
1572 uc_info->in_snd_device = SND_DEVICE_NONE;
1573 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001574 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001575 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001576 if (is_offload_usecase(out->usecase)) {
1577 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001578 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1579 }
1580 }
Mingming Yin9c041392014-05-01 15:37:31 -07001581 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1582 if (!strncmp("true", prop_value, 4)) {
1583 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001584 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1585 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001586 check_and_set_hdmi_channels(adev, sink_channels);
1587 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001588 if (is_offload_usecase(out->usecase)) {
1589 unsigned int ch_count = out->compr_config.codec->ch_in;
1590 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1591 /* backend channel config for passthrough stream is stereo */
1592 ch_count = 2;
1593 check_and_set_hdmi_channels(adev, ch_count);
1594 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001595 check_and_set_hdmi_channels(adev, out->config.channels);
1596 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001597 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001598 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001599 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 select_devices(adev, out->usecase);
1602
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001603 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1604 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001605 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001606 unsigned int flags = PCM_OUT;
1607 unsigned int pcm_open_retry_count = 0;
1608 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1609 flags |= PCM_MMAP | PCM_NOIRQ;
1610 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1611 } else
1612 flags |= PCM_MONOTONIC;
1613
1614 while (1) {
1615 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1616 flags, &out->config);
1617 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1618 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1619 if (out->pcm != NULL) {
1620 pcm_close(out->pcm);
1621 out->pcm = NULL;
1622 }
1623 if (pcm_open_retry_count-- == 0) {
1624 ret = -EIO;
1625 goto error_open;
1626 }
1627 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1628 continue;
1629 }
1630 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001631 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001632
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001633 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1634 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001635
1636 ALOGV("%s: pcm_prepare start", __func__);
1637 if (pcm_is_ready(out->pcm))
1638 pcm_prepare(out->pcm);
1639
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001640 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001641 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1642 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001644 out->compr = compress_open(adev->snd_card,
1645 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001646 COMPRESS_IN, &out->compr_config);
1647 if (out->compr && !is_compress_ready(out->compr)) {
1648 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1649 compress_close(out->compr);
1650 out->compr = NULL;
1651 ret = -EIO;
1652 goto error_open;
1653 }
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301654 /* compress_open sends params of the track, so reset the flag here */
1655 out->is_compr_metadata_avail = false;
1656
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 if (out->offload_callback)
1658 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001659
Fred Oh3f43e742015-03-04 18:42:34 -08001660 /* Since small bufs uses blocking writes, a write will be blocked
1661 for the default max poll time (20s) in the event of an SSR.
1662 Reduce the poll time to observe and deal with SSR faster.
1663 */
1664 if (out->use_small_bufs) {
1665 compress_set_max_poll_wait(out->compr, 1000);
1666 }
1667
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001668 audio_extn_dts_create_state_notifier_node(out->usecase);
1669 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1670 popcount(out->channel_mask),
1671 out->playback_started);
1672
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001673#ifdef DS1_DOLBY_DDP_ENABLED
1674 if (audio_extn_is_dolby_format(out->format))
1675 audio_extn_dolby_send_ddp_endp_params(adev);
1676#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001677 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1678 if (adev->visualizer_start_output != NULL)
1679 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1680 if (adev->offload_effects_start_output != NULL)
1681 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001682 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001683 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001685
Eric Laurent994a6932013-07-17 11:51:42 -07001686 ALOGV("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001689error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001691error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001692 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693}
1694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695static int check_input_parameters(uint32_t sample_rate,
1696 audio_format_t format,
1697 int channel_count)
1698{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001699 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001701 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001702 !voice_extn_compress_voip_is_format_supported(format) &&
1703 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001704
1705 switch (channel_count) {
1706 case 1:
1707 case 2:
1708 case 6:
1709 break;
1710 default:
1711 ret = -EINVAL;
1712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
1714 switch (sample_rate) {
1715 case 8000:
1716 case 11025:
1717 case 12000:
1718 case 16000:
1719 case 22050:
1720 case 24000:
1721 case 32000:
1722 case 44100:
1723 case 48000:
1724 break;
1725 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001726 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 }
1728
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001729 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730}
1731
1732static size_t get_input_buffer_size(uint32_t sample_rate,
1733 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001734 int channel_count,
1735 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736{
1737 size_t size = 0;
1738
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001739 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1740 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001742 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001743 if (is_low_latency)
1744 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001745 /* ToDo: should use frame_size computed based on the format and
1746 channel_count here. */
1747 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001749 /* make sure the size is multiple of 32 bytes
1750 * At 48 kHz mono 16-bit PCM:
1751 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1752 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1753 */
1754 size += 0x1f;
1755 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001756
1757 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758}
1759
1760static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1761{
1762 struct stream_out *out = (struct stream_out *)stream;
1763
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765}
1766
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001767static int out_set_sample_rate(struct audio_stream *stream __unused,
1768 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769{
1770 return -ENOSYS;
1771}
1772
1773static size_t out_get_buffer_size(const struct audio_stream *stream)
1774{
1775 struct stream_out *out = (struct stream_out *)stream;
1776
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001777 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001779 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1780 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001782 return out->config.period_size *
1783 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784}
1785
1786static uint32_t out_get_channels(const struct audio_stream *stream)
1787{
1788 struct stream_out *out = (struct stream_out *)stream;
1789
1790 return out->channel_mask;
1791}
1792
1793static audio_format_t out_get_format(const struct audio_stream *stream)
1794{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 struct stream_out *out = (struct stream_out *)stream;
1796
1797 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798}
1799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001800static int out_set_format(struct audio_stream *stream __unused,
1801 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802{
1803 return -ENOSYS;
1804}
1805
1806static int out_standby(struct audio_stream *stream)
1807{
1808 struct stream_out *out = (struct stream_out *)stream;
1809 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001810
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301811 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1812 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001813 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1814 /* Ignore standby in case of voip call because the voip output
1815 * stream is closed in adev_close_output_stream()
1816 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301817 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001818 return 0;
1819 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001821 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001823 if (adev->adm_deregister_stream)
1824 adev->adm_deregister_stream(adev->adm_data, out->handle);
1825
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001826 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001828 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001829 if (out->pcm) {
1830 pcm_close(out->pcm);
1831 out->pcm = NULL;
1832 }
1833 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001834 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301836 out->send_next_track_params = false;
1837 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838 out->gapless_mdata.encoder_delay = 0;
1839 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001840 if (out->compr != NULL) {
1841 compress_close(out->compr);
1842 out->compr = NULL;
1843 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001846 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 }
1848 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001849 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 return 0;
1851}
1852
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001853static int out_dump(const struct audio_stream *stream __unused,
1854 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855{
1856 return 0;
1857}
1858
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1860{
1861 int ret = 0;
1862 char value[32];
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
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001871 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1872 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301873 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001874 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001875 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1876 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301877 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001878 }
1879
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001880 ALOGV("%s new encoder delay %u and padding %u", __func__,
1881 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1882
1883 return 0;
1884}
1885
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001886static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1887{
1888 return out == adev->primary_output || out == adev->voice_tx_output;
1889}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1892{
1893 struct stream_out *out = (struct stream_out *)stream;
1894 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001895 struct audio_usecase *usecase;
1896 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 struct str_parms *parms;
1898 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001899 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001900 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901
sangwoobc677242013-08-08 16:53:43 +09001902 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301905 if (!parms)
1906 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001907 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1908 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909 val = atoi(value);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001910 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001911 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001913 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301914 * When HDMI cable is unplugged/usb hs is disconnected the
1915 * music playback is paused and the policy manager sends routing=0
1916 * But the audioflingercontinues to write data until standby time
1917 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 * Avoid this by routing audio to speaker until standby.
1919 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301920 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1921 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001922 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001923 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1924 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 }
1926
1927 /*
1928 * select_devices() call below switches all the usecases on the same
1929 * backend to the new device. Refer to check_usecases_codec_backend() in
1930 * the select_devices(). But how do we undo this?
1931 *
1932 * For example, music playback is active on headset (deep-buffer usecase)
1933 * and if we go to ringtones and select a ringtone, low-latency usecase
1934 * will be started on headset+speaker. As we can't enable headset+speaker
1935 * and headset devices at the same time, select_devices() switches the music
1936 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1937 * So when the ringtone playback is completed, how do we undo the same?
1938 *
1939 * We are relying on the out_set_parameters() call on deep-buffer output,
1940 * once the ringtone playback is ended.
1941 * NOTE: We should not check if the current devices are same as new devices.
1942 * Because select_devices() must be called to switch back the music
1943 * playback to headset.
1944 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001945 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001946 out->devices = val;
1947
1948 if (!out->standby)
1949 select_devices(adev, out->usecase);
1950
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001951 if (output_drives_call(adev, out)) {
1952 if(!voice_is_in_call(adev)) {
1953 if (adev->mode == AUDIO_MODE_IN_CALL) {
1954 adev->current_call_output = out;
1955 ret = voice_start_call(adev);
1956 }
1957 } else {
1958 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001959 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001960 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001961 }
1962 }
1963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001965 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001967
1968 if (out == adev->primary_output) {
1969 pthread_mutex_lock(&adev->lock);
1970 audio_extn_set_parameters(adev, parms);
1971 pthread_mutex_unlock(&adev->lock);
1972 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001973 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001974 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001975 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001976
1977 audio_extn_dts_create_state_notifier_node(out->usecase);
1978 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1979 popcount(out->channel_mask),
1980 out->playback_started);
1981
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001982 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001983 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301986error:
Eric Laurent994a6932013-07-17 11:51:42 -07001987 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 return ret;
1989}
1990
1991static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1992{
1993 struct stream_out *out = (struct stream_out *)stream;
1994 struct str_parms *query = str_parms_create_str(keys);
1995 char *str;
1996 char value[256];
1997 struct str_parms *reply = str_parms_create();
1998 size_t i, j;
1999 int ret;
2000 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002001
2002 if (!query || !reply) {
2003 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2004 return NULL;
2005 }
2006
Eric Laurent994a6932013-07-17 11:51:42 -07002007 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2009 if (ret >= 0) {
2010 value[0] = '\0';
2011 i = 0;
2012 while (out->supported_channel_masks[i] != 0) {
2013 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2014 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2015 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002016 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002018 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 first = false;
2020 break;
2021 }
2022 }
2023 i++;
2024 }
2025 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2026 str = str_parms_to_str(reply);
2027 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002028 voice_extn_out_get_parameters(out, query, reply);
2029 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002030 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002031 free(str);
2032 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002035
2036 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2037 if (ret >= 0) {
2038 value[0] = '\0';
2039 i = 0;
2040 first = true;
2041 while (out->supported_formats[i] != 0) {
2042 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2043 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2044 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002045 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002046 }
2047 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2048 first = false;
2049 break;
2050 }
2051 }
2052 i++;
2053 }
2054 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2055 str = str_parms_to_str(reply);
2056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 str_parms_destroy(query);
2058 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002059 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 return str;
2061}
2062
2063static uint32_t out_get_latency(const struct audio_stream_out *stream)
2064{
2065 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002066 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067
Alexy Josephaa54c872014-12-03 02:46:47 -08002068 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002069 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002070 } else {
2071 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002072 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002073 }
2074
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302075 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002076 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077}
2078
2079static int out_set_volume(struct audio_stream_out *stream, float left,
2080 float right)
2081{
Eric Laurenta9024de2013-04-04 09:19:12 -07002082 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 int volume[2];
2084
Eric Laurenta9024de2013-04-04 09:19:12 -07002085 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2086 /* only take left channel into account: the API is for stereo anyway */
2087 out->muted = (left == 0.0f);
2088 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002089 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002090 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2091 /*
2092 * Set mute or umute on HDMI passthrough stream.
2093 * Only take left channel into account.
2094 * Mute is 0 and unmute 1
2095 */
2096 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2097 } else {
2098 char mixer_ctl_name[128];
2099 struct audio_device *adev = out->dev;
2100 struct mixer_ctl *ctl;
2101 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002102 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002104 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2105 "Compress Playback %d Volume", pcm_device_id);
2106 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2107 if (!ctl) {
2108 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2109 __func__, mixer_ctl_name);
2110 return -EINVAL;
2111 }
2112 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2113 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2114 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2115 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002117 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 return -ENOSYS;
2120}
2121
2122static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2123 size_t bytes)
2124{
2125 struct stream_out *out = (struct stream_out *)stream;
2126 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302127 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002128 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002130 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302131
Naresh Tanniru80659832014-06-04 18:17:56 +05302132 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002133 // increase written size during SSR to avoid mismatch
2134 // with the written frames count in AF
2135 if (!is_offload_usecase(out->usecase))
2136 out->written += bytes / (out->config.channels * sizeof(short));
2137
Naresh Tanniru80659832014-06-04 18:17:56 +05302138 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302139 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302140 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302141 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002142 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302143 //during SSR for compress usecase we should return error to flinger
2144 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2145 pthread_mutex_unlock(&out->lock);
2146 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302147 }
2148 }
2149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002151 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002152 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002153 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2154 ret = voice_extn_compress_voip_start_output_stream(out);
2155 else
2156 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002157 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002160 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 goto exit;
2162 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002163 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2164 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302167 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2168 setChannelStatus(out, buffer, bytes);
2169 adev->mChannelStatusSet = true;
2170 }
2171
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002172 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002173 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002174 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002175 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002176 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2177 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302178 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2179 ALOGD("copl(%p):send next track params in gapless", out);
2180 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2181 out->send_next_track_params = false;
2182 out->is_compr_metadata_avail = false;
2183 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002184 }
2185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002186 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302187 if (ret < 0)
2188 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002189 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002190 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302191 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002192 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302193 } else if (-ENETRESET == ret) {
2194 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2195 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2196 pthread_mutex_unlock(&out->lock);
2197 out_standby(&out->stream.common);
2198 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302200 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002202 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002203 out->playback_started = 1;
2204 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002205
2206 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2207 popcount(out->channel_mask),
2208 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 }
2210 pthread_mutex_unlock(&out->lock);
2211 return ret;
2212 } else {
2213 if (out->pcm) {
2214 if (out->muted)
2215 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002217 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002218
2219 if (adev->adm_request_focus)
2220 adev->adm_request_focus(adev->adm_data, out->handle);
2221
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002222 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2223 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2224 else
2225 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002226
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302227 if (ret < 0)
2228 ret = -errno;
2229 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002230 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002231
2232 if (adev->adm_abandon_focus)
2233 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 }
2236
2237exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302238 /* ToDo: There may be a corner case when SSR happens back to back during
2239 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302240 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302241 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302242 }
2243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 pthread_mutex_unlock(&out->lock);
2245
2246 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002247 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002248 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302249 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302250 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302251 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302252 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302253 out->standby = true;
2254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002256 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302257 out_get_sample_rate(&out->stream.common));
2258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
2260 return bytes;
2261}
2262
2263static int out_get_render_position(const struct audio_stream_out *stream,
2264 uint32_t *dsp_frames)
2265{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302267 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002268
2269 if (dsp_frames == NULL)
2270 return -EINVAL;
2271
2272 *dsp_frames = 0;
2273 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002274 ssize_t ret = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002275 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302277 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302279 if (ret < 0)
2280 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281 ALOGVV("%s rendered frames %d sample_rate %d",
2282 __func__, *dsp_frames, out->sample_rate);
2283 }
2284 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302285 if (-ENETRESET == ret) {
2286 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2287 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2288 return -EINVAL;
2289 } else if(ret < 0) {
2290 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2291 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302292 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2293 /*
2294 * Handle corner case where compress session is closed during SSR
2295 * and timestamp is queried
2296 */
2297 ALOGE(" ERROR: sound card not active, return error");
2298 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302299 } else {
2300 return 0;
2301 }
Zhou Song32a556e2015-05-05 10:46:56 +08002302 } else if (audio_is_linear_pcm(out->format)) {
2303 *dsp_frames = out->written;
2304 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 } else
2306 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307}
2308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002309static int out_add_audio_effect(const struct audio_stream *stream __unused,
2310 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311{
2312 return 0;
2313}
2314
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002315static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2316 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317{
2318 return 0;
2319}
2320
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002321static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2322 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323{
2324 return -EINVAL;
2325}
2326
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002327static int out_get_presentation_position(const struct audio_stream_out *stream,
2328 uint64_t *frames, struct timespec *timestamp)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
2331 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002332 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002333
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002334 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002335
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002336 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002337 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302338 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002339 &out->sample_rate);
2340 ALOGVV("%s rendered frames %ld sample_rate %d",
2341 __func__, dsp_frames, out->sample_rate);
2342 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302343 if (ret < 0)
2344 ret = -errno;
2345 if (-ENETRESET == ret) {
2346 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2347 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2348 ret = -EINVAL;
2349 } else
2350 ret = 0;
2351
Eric Laurent949a0892013-09-20 09:20:13 -07002352 /* this is the best we can do */
2353 clock_gettime(CLOCK_MONOTONIC, timestamp);
2354 }
2355 } else {
2356 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002357 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002358 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2359 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002360 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002361 // This adjustment accounts for buffering after app processor.
2362 // It is based on estimated DSP latency per use case, rather than exact.
2363 signed_frames -=
2364 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2365
Eric Laurent949a0892013-09-20 09:20:13 -07002366 // It would be unusual for this value to be negative, but check just in case ...
2367 if (signed_frames >= 0) {
2368 *frames = signed_frames;
2369 ret = 0;
2370 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002371 }
2372 }
2373 }
2374
2375 pthread_mutex_unlock(&out->lock);
2376
2377 return ret;
2378}
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380static int out_set_callback(struct audio_stream_out *stream,
2381 stream_callback_t callback, void *cookie)
2382{
2383 struct stream_out *out = (struct stream_out *)stream;
2384
2385 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002386 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 out->offload_callback = callback;
2388 out->offload_cookie = cookie;
2389 pthread_mutex_unlock(&out->lock);
2390 return 0;
2391}
2392
2393static int out_pause(struct audio_stream_out* stream)
2394{
2395 struct stream_out *out = (struct stream_out *)stream;
2396 int status = -ENOSYS;
2397 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002398 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002399 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002400 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302402 struct audio_device *adev = out->dev;
2403 int snd_scard_state = get_snd_card_state(adev);
2404
2405 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2406 status = compress_pause(out->compr);
2407
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002409
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302410 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002411 audio_extn_dts_notify_playback_state(out->usecase, 0,
2412 out->sample_rate, popcount(out->channel_mask),
2413 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 }
2415 pthread_mutex_unlock(&out->lock);
2416 }
2417 return status;
2418}
2419
2420static int out_resume(struct audio_stream_out* stream)
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423 int status = -ENOSYS;
2424 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002425 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002426 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 status = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002428 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002429 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302430 struct audio_device *adev = out->dev;
2431 int snd_scard_state = get_snd_card_state(adev);
2432
2433 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2434 status = compress_resume(out->compr);
2435
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002437
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302438 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002439 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2440 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 }
2442 pthread_mutex_unlock(&out->lock);
2443 }
2444 return status;
2445}
2446
2447static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450 int status = -ENOSYS;
2451 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002452 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002453 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2455 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2456 else
2457 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2458 pthread_mutex_unlock(&out->lock);
2459 }
2460 return status;
2461}
2462
2463static int out_flush(struct audio_stream_out* stream)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002467 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002468 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002469 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 stop_compressed_output_l(out);
2471 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002472 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 return 0;
2474 }
2475 return -ENOSYS;
2476}
2477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478/** audio_stream_in implementation **/
2479static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2480{
2481 struct stream_in *in = (struct stream_in *)stream;
2482
2483 return in->config.rate;
2484}
2485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002486static int in_set_sample_rate(struct audio_stream *stream __unused,
2487 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488{
2489 return -ENOSYS;
2490}
2491
2492static size_t in_get_buffer_size(const struct audio_stream *stream)
2493{
2494 struct stream_in *in = (struct stream_in *)stream;
2495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002496 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2497 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002498 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2499 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002500
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002501 return in->config.period_size *
2502 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
2505static uint32_t in_get_channels(const struct audio_stream *stream)
2506{
2507 struct stream_in *in = (struct stream_in *)stream;
2508
2509 return in->channel_mask;
2510}
2511
2512static audio_format_t in_get_format(const struct audio_stream *stream)
2513{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002514 struct stream_in *in = (struct stream_in *)stream;
2515
2516 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517}
2518
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002519static int in_set_format(struct audio_stream *stream __unused,
2520 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521{
2522 return -ENOSYS;
2523}
2524
2525static int in_standby(struct audio_stream *stream)
2526{
2527 struct stream_in *in = (struct stream_in *)stream;
2528 struct audio_device *adev = in->dev;
2529 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302530 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2531 stream, in->usecase, use_case_table[in->usecase]);
2532
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002533 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2534 /* Ignore standby in case of voip call because the voip input
2535 * stream is closed in adev_close_input_stream()
2536 */
2537 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2538 return status;
2539 }
2540
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002541 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002542 if (!in->standby && in->is_st_session) {
2543 ALOGD("%s: sound trigger pcm stop lab", __func__);
2544 audio_extn_sound_trigger_stop_lab(in);
2545 in->standby = 1;
2546 }
2547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002549 if (adev->adm_deregister_stream)
2550 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2551
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002552 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002554 if (in->pcm) {
2555 pcm_close(in->pcm);
2556 in->pcm = NULL;
2557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002559 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 }
2561 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002562 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 return status;
2564}
2565
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002566static int in_dump(const struct audio_stream *stream __unused,
2567 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568{
2569 return 0;
2570}
2571
2572static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2573{
2574 struct stream_in *in = (struct stream_in *)stream;
2575 struct audio_device *adev = in->dev;
2576 struct str_parms *parms;
2577 char *str;
2578 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002579 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302581 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 parms = str_parms_create_str(kvpairs);
2583
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302584 if (!parms)
2585 goto error;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002586 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002587 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002588
2589 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2590 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 val = atoi(value);
2592 /* no audio source uses val == 0 */
2593 if ((in->source != val) && (val != 0)) {
2594 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002595 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2596 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2597 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2598 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002599 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002600 err = voice_extn_compress_voip_open_input_stream(in);
2601 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002602 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002603 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002604 }
2605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606 }
2607 }
2608
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002609 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2610 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002612 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 in->device = val;
2614 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002615 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 }
2618 }
2619
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002620done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002622 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623
2624 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302625error:
Eric Laurent994a6932013-07-17 11:51:42 -07002626 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 return ret;
2628}
2629
2630static char* in_get_parameters(const struct audio_stream *stream,
2631 const char *keys)
2632{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002633 struct stream_in *in = (struct stream_in *)stream;
2634 struct str_parms *query = str_parms_create_str(keys);
2635 char *str;
2636 char value[256];
2637 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002638
2639 if (!query || !reply) {
2640 ALOGE("in_get_parameters: failed to create query or reply");
2641 return NULL;
2642 }
2643
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002644 ALOGV("%s: enter: keys - %s", __func__, keys);
2645
2646 voice_extn_in_get_parameters(in, query, reply);
2647
2648 str = str_parms_to_str(reply);
2649 str_parms_destroy(query);
2650 str_parms_destroy(reply);
2651
2652 ALOGV("%s: exit: returns - %s", __func__, str);
2653 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654}
2655
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002656static int in_set_gain(struct audio_stream_in *stream __unused,
2657 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658{
2659 return 0;
2660}
2661
2662static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2663 size_t bytes)
2664{
2665 struct stream_in *in = (struct stream_in *)stream;
2666 struct audio_device *adev = in->dev;
2667 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302668 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002670 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302671
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002672 if (in->is_st_session) {
2673 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2674 /* Read from sound trigger HAL */
2675 audio_extn_sound_trigger_read(in, buffer, bytes);
2676 pthread_mutex_unlock(&in->lock);
2677 return bytes;
2678 }
2679
2680 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2681 ALOGD(" %s: sound card is not active/SSR state", __func__);
2682 ret= -EIO;;
2683 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302684 }
2685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002687 pthread_mutex_lock(&adev->lock);
2688 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2689 ret = voice_extn_compress_voip_start_input_stream(in);
2690 else
2691 ret = start_input_stream(in);
2692 pthread_mutex_unlock(&adev->lock);
2693 if (ret != 0) {
2694 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
2696 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002697 if (adev->adm_register_input_stream)
2698 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700
Naresh Tanniru4a080142015-06-15 10:35:19 -07002701 if (adev->adm_request_focus)
2702 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002705 if (audio_extn_ssr_get_enabled() &&
2706 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002707 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002708 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2709 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002710 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2711 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002712 else
2713 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302714 if (ret < 0)
2715 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 }
2717
Naresh Tanniru4a080142015-06-15 10:35:19 -07002718 if (adev->adm_abandon_focus)
2719 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 /*
2722 * Instead of writing zeroes here, we could trust the hardware
2723 * to always provide zeroes when muted.
2724 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302725 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2726 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 memset(buffer, 0, bytes);
2728
2729exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302730 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302731 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002732 if (-ENETRESET == ret)
2733 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 pthread_mutex_unlock(&in->lock);
2736
2737 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302738 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302739 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302740 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302741 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302742 in->standby = true;
2743 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302744 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002746 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002747 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302748 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 }
2750 return bytes;
2751}
2752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002753static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754{
2755 return 0;
2756}
2757
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002758static int add_remove_audio_effect(const struct audio_stream *stream,
2759 effect_handle_t effect,
2760 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002762 struct stream_in *in = (struct stream_in *)stream;
2763 int status = 0;
2764 effect_descriptor_t desc;
2765
2766 status = (*effect)->get_descriptor(effect, &desc);
2767 if (status != 0)
2768 return status;
2769
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002770 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002771 pthread_mutex_lock(&in->dev->lock);
2772 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2773 in->enable_aec != enable &&
2774 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2775 in->enable_aec = enable;
2776 if (!in->standby)
2777 select_devices(in->dev, in->usecase);
2778 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002779 if (in->enable_ns != enable &&
2780 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2781 in->enable_ns = enable;
2782 if (!in->standby)
2783 select_devices(in->dev, in->usecase);
2784 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002785 pthread_mutex_unlock(&in->dev->lock);
2786 pthread_mutex_unlock(&in->lock);
2787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 return 0;
2789}
2790
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002791static int in_add_audio_effect(const struct audio_stream *stream,
2792 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793{
Eric Laurent994a6932013-07-17 11:51:42 -07002794 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002795 return add_remove_audio_effect(stream, effect, true);
2796}
2797
2798static int in_remove_audio_effect(const struct audio_stream *stream,
2799 effect_handle_t effect)
2800{
Eric Laurent994a6932013-07-17 11:51:42 -07002801 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002802 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803}
2804
2805static int adev_open_output_stream(struct audio_hw_device *dev,
2806 audio_io_handle_t handle,
2807 audio_devices_t devices,
2808 audio_output_flags_t flags,
2809 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002810 struct audio_stream_out **stream_out,
2811 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812{
2813 struct audio_device *adev = (struct audio_device *)dev;
2814 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002815 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002816 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302819
2820 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2821 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2822 ALOGE(" sound card is not active rejecting compress output open request");
2823 return -EINVAL;
2824 }
2825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2827
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302828 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2829 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2830 devices, flags, &out->stream);
2831
2832
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002833 if (!out) {
2834 return -ENOMEM;
2835 }
2836
Haynes Mathew George204045b2015-02-25 20:32:03 -08002837 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002838 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002839 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841 if (devices == AUDIO_DEVICE_NONE)
2842 devices = AUDIO_DEVICE_OUT_SPEAKER;
2843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 out->flags = flags;
2845 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002846 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002847 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 out->sample_rate = config->sample_rate;
2849 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2850 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002851 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002852 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002853 out->non_blocking = 0;
2854 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302856 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2857 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002858 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2859 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2860
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002861 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002862 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2863 ret = read_hdmi_channel_masks(out);
2864
2865 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2866 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002867 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002868 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002869 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002870
2871 if (config->sample_rate == 0)
2872 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2873 if (config->channel_mask == 0)
2874 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2875
2876 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2879 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002881 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002883 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2884 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002885 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002886 ret = voice_extn_compress_voip_open_output_stream(out);
2887 if (ret != 0) {
2888 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2889 __func__, ret);
2890 goto error_open;
2891 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2893 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2894 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2895 ALOGE("%s: Unsupported Offload information", __func__);
2896 ret = -EINVAL;
2897 goto error_open;
2898 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002899
2900 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2901 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2902 ALOGV("read and update_pass through formats");
2903 ret = audio_extn_dolby_update_passt_formats(adev, out);
2904 if(ret != 0) {
2905 goto error_open;
2906 }
2907 if(config->offload_info.format == 0)
2908 config->offload_info.format = out->supported_formats[0];
2909 }
2910
Mingming Yin90310102013-11-13 16:57:00 -08002911 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002912 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 ALOGE("%s: Unsupported audio format", __func__);
2914 ret = -EINVAL;
2915 goto error_open;
2916 }
2917
2918 out->compr_config.codec = (struct snd_codec *)
2919 calloc(1, sizeof(struct snd_codec));
2920
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002921 if (!out->compr_config.codec) {
2922 ret = -ENOMEM;
2923 goto error_open;
2924 }
2925
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002926 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 if (config->offload_info.channel_mask)
2928 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002929 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002931 config->offload_info.channel_mask = config->channel_mask;
2932 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002933 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 out->sample_rate = config->offload_info.sample_rate;
2935
2936 out->stream.set_callback = out_set_callback;
2937 out->stream.pause = out_pause;
2938 out->stream.resume = out_resume;
2939 out->stream.drain = out_drain;
2940 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002941 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002943 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002944 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002945 audio_extn_dolby_get_snd_codec_id(adev, out,
2946 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002947 else
2948 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302950 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002951 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002952 platform_get_pcm_offload_buffer_size(&config->offload_info);
2953 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2954 out->compr_config.fragment_size =
2955 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002956 } else {
2957 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002958 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002959 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002960 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2961 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002962 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 out->compr_config.codec->bit_rate =
2964 config->offload_info.bit_rate;
2965 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002966 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302968 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002969 /*TODO: Do we need to change it for passthrough */
2970 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971
Manish Dewangan93672f12015-08-24 20:30:31 +05302972 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
2973 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
2974 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
2975 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002976 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2977 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002978 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002979 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2980
Mingming Yin3ee55c62014-08-04 14:23:35 -07002981 if (out->bit_width == 24) {
2982 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2983 }
2984
Amit Shekhar6f461b12014-08-01 14:52:58 -07002985 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302986 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002988 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2989 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002990
Sharad Sangleb27354b2015-06-18 15:58:55 +05302991 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002992 //this flag is set from framework only if its for PCM formats
2993 //no need to check for PCM format again
2994 out->non_blocking = 0;
2995 out->use_small_bufs = true;
2996 ALOGI("Keep write blocking for small buff: non_blockling %d",
2997 out->non_blocking);
2998 }
2999
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003000 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05303001 out->send_next_track_params = false;
3002 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003003 out->offload_state = OFFLOAD_STATE_IDLE;
3004 out->playback_started = 0;
3005
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003006 audio_extn_dts_create_state_notifier_node(out->usecase);
3007
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008 create_offload_callback_thread(out);
3009 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3010 __func__, config->offload_info.version,
3011 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003012 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003013 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003014 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3015 ret = voice_check_and_set_incall_music_usecase(adev, out);
3016 if (ret != 0) {
3017 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3018 __func__, ret);
3019 goto error_open;
3020 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003021 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3022 if (config->sample_rate == 0)
3023 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3024 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3025 config->sample_rate != 8000) {
3026 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3027 ret = -EINVAL;
3028 goto error_open;
3029 }
3030 out->sample_rate = config->sample_rate;
3031 out->config.rate = config->sample_rate;
3032 if (config->format == AUDIO_FORMAT_DEFAULT)
3033 config->format = AUDIO_FORMAT_PCM_16_BIT;
3034 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3035 config->format = AUDIO_FORMAT_PCM_16_BIT;
3036 ret = -EINVAL;
3037 goto error_open;
3038 }
3039 out->format = config->format;
3040 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3041 out->config = pcm_config_afe_proxy_playback;
3042 adev->voice_tx_output = out;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003043 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3044 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3045 out->config = pcm_config_low_latency;
3046 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003047 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003048 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3050 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003052 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3053 format = AUDIO_FORMAT_PCM_16_BIT;
3054 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3055 out->config = pcm_config_deep_buffer;
3056 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003057 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003058 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003059 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003060 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003061 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003062 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 }
3064
Amit Shekhar1d896042014-10-03 13:16:09 -07003065 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3066 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003067 /* TODO remove this hardcoding and check why width is zero*/
3068 if (out->bit_width == 0)
3069 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003070 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3071 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003072 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303073 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003074 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3075 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3076 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003077 if(adev->primary_output == NULL)
3078 adev->primary_output = out;
3079 else {
3080 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003081 ret = -EEXIST;
3082 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003083 }
3084 }
3085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 /* Check if this usecase is already existing */
3087 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003088 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3089 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003092 ret = -EEXIST;
3093 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 }
3095 pthread_mutex_unlock(&adev->lock);
3096
3097 out->stream.common.get_sample_rate = out_get_sample_rate;
3098 out->stream.common.set_sample_rate = out_set_sample_rate;
3099 out->stream.common.get_buffer_size = out_get_buffer_size;
3100 out->stream.common.get_channels = out_get_channels;
3101 out->stream.common.get_format = out_get_format;
3102 out->stream.common.set_format = out_set_format;
3103 out->stream.common.standby = out_standby;
3104 out->stream.common.dump = out_dump;
3105 out->stream.common.set_parameters = out_set_parameters;
3106 out->stream.common.get_parameters = out_get_parameters;
3107 out->stream.common.add_audio_effect = out_add_audio_effect;
3108 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3109 out->stream.get_latency = out_get_latency;
3110 out->stream.set_volume = out_set_volume;
3111 out->stream.write = out_write;
3112 out->stream.get_render_position = out_get_render_position;
3113 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003114 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003117 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003118 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
3120 config->format = out->stream.common.get_format(&out->stream.common);
3121 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3122 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3123
3124 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303125 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3126 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003127
3128 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3129 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3130 popcount(out->channel_mask), out->playback_started);
3131
Eric Laurent994a6932013-07-17 11:51:42 -07003132 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003134
3135error_open:
3136 free(out);
3137 *stream_out = NULL;
3138 ALOGD("%s: exit: ret %d", __func__, ret);
3139 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140}
3141
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003142static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 struct audio_stream_out *stream)
3144{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 struct stream_out *out = (struct stream_out *)stream;
3146 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003147 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303149 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3150
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003151 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303152 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003153 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303154 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003155 if(ret != 0)
3156 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3157 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003158 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003159 out_standby(&stream->common);
3160
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003161 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003162 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003164 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003165 if (out->compr_config.codec != NULL)
3166 free(out->compr_config.codec);
3167 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003168
3169 if (adev->voice_tx_output == out)
3170 adev->voice_tx_output = NULL;
3171
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 pthread_cond_destroy(&out->cond);
3173 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003175 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176}
3177
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003178static void close_compress_sessions(struct audio_device *adev)
3179{
Mingming Yin7b762e72015-03-04 13:47:32 -08003180 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303181 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003182 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003183 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303184
3185 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003186 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303187 if (is_offload_usecase(usecase->id)) {
3188 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003189 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3190 out = usecase->stream.out;
3191 pthread_mutex_unlock(&adev->lock);
3192 out_standby(&out->stream.common);
3193 pthread_mutex_lock(&adev->lock);
3194 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303195 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003196 }
3197 pthread_mutex_unlock(&adev->lock);
3198}
3199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3201{
3202 struct audio_device *adev = (struct audio_device *)dev;
3203 struct str_parms *parms;
3204 char *str;
3205 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003206 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003207 int ret;
3208 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003210 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303213 if (!parms)
3214 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003215 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3216 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303217 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303218 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303219 struct listnode *node;
3220 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303221 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303222 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003223 //close compress sessions on OFFLINE status
3224 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303225 } else if (strstr(snd_card_status, "ONLINE")) {
3226 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303227 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303228 if (!platform_is_acdb_initialized(adev->platform)) {
3229 ret = platform_acdb_init(adev->platform);
3230 if(ret)
3231 ALOGE("acdb initialization is failed");
3232
3233 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303234 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303235 }
3236
3237 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003238 status = voice_set_parameters(adev, parms);
3239 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003240 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003242 status = platform_set_parameters(adev->platform, parms);
3243 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003244 goto done;
3245
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003246 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3247 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003248 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3250 adev->bluetooth_nrec = true;
3251 else
3252 adev->bluetooth_nrec = false;
3253 }
3254
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003255 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3256 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3258 adev->screen_off = false;
3259 else
3260 adev->screen_off = true;
3261 }
3262
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003263 ret = str_parms_get_int(parms, "rotation", &val);
3264 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003265 bool reverse_speakers = false;
3266 switch(val) {
3267 // FIXME: note that the code below assumes that the speakers are in the correct placement
3268 // relative to the user when the device is rotated 90deg from its default rotation. This
3269 // assumption is device-specific, not platform-specific like this code.
3270 case 270:
3271 reverse_speakers = true;
3272 break;
3273 case 0:
3274 case 90:
3275 case 180:
3276 break;
3277 default:
3278 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003279 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003280 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003281 if (status == 0) {
3282 if (adev->speaker_lr_swap != reverse_speakers) {
3283 adev->speaker_lr_swap = reverse_speakers;
3284 // only update the selected device if there is active pcm playback
3285 struct audio_usecase *usecase;
3286 struct listnode *node;
3287 list_for_each(node, &adev->usecase_list) {
3288 usecase = node_to_item(node, struct audio_usecase, list);
3289 if (usecase->type == PCM_PLAYBACK) {
3290 select_devices(adev, usecase->id);
3291 break;
3292 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003293 }
3294 }
3295 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003296 }
3297
Mingming Yin514a8bc2014-07-29 15:22:21 -07003298 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3299 if (ret >= 0) {
3300 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3301 adev->bt_wb_speech_enabled = true;
3302 else
3303 adev->bt_wb_speech_enabled = false;
3304 }
3305
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003306 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3307 if (ret >= 0) {
3308 val = atoi(value);
3309 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3310 ALOGV("cache new edid");
3311 platform_cache_edid(adev->platform);
3312 }
3313 }
3314
3315 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3316 if (ret >= 0) {
3317 val = atoi(value);
3318 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3319 ALOGV("invalidate cached edid");
3320 platform_invalidate_edid(adev->platform);
3321 }
3322 }
3323
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003324 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003325
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003326done:
3327 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003328 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303329error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003330 ALOGV("%s: exit with code(%d)", __func__, status);
3331 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332}
3333
3334static char* adev_get_parameters(const struct audio_hw_device *dev,
3335 const char *keys)
3336{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003337 struct audio_device *adev = (struct audio_device *)dev;
3338 struct str_parms *reply = str_parms_create();
3339 struct str_parms *query = str_parms_create_str(keys);
3340 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303341 char value[256] = {0};
3342 int ret = 0;
3343
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003344 if (!query || !reply) {
3345 ALOGE("adev_get_parameters: failed to create query or reply");
3346 return NULL;
3347 }
3348
Naresh Tannirud7205b62014-06-20 02:54:48 +05303349 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3350 sizeof(value));
3351 if (ret >=0) {
3352 int val = 1;
3353 pthread_mutex_lock(&adev->snd_card_status.lock);
3354 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3355 val = 0;
3356 pthread_mutex_unlock(&adev->snd_card_status.lock);
3357 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3358 goto exit;
3359 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003360
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003361 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003362 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003363 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003364 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303365 pthread_mutex_unlock(&adev->lock);
3366
Naresh Tannirud7205b62014-06-20 02:54:48 +05303367exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003368 str = str_parms_to_str(reply);
3369 str_parms_destroy(query);
3370 str_parms_destroy(reply);
3371
3372 ALOGV("%s: exit: returns - %s", __func__, str);
3373 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374}
3375
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003376static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377{
3378 return 0;
3379}
3380
3381static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3382{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003383 int ret;
3384 struct audio_device *adev = (struct audio_device *)dev;
3385 pthread_mutex_lock(&adev->lock);
3386 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003387 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003388 pthread_mutex_unlock(&adev->lock);
3389 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390}
3391
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003392static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3393 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394{
3395 return -ENOSYS;
3396}
3397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003398static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3399 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400{
3401 return -ENOSYS;
3402}
3403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003404static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3405 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406{
3407 return -ENOSYS;
3408}
3409
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003410static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3411 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412{
3413 return -ENOSYS;
3414}
3415
3416static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3417{
3418 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 pthread_mutex_lock(&adev->lock);
3421 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003422 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003424 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3425 voice_is_in_call(adev)) {
3426 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303427 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003428 adev->current_call_output = NULL;
3429 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430 }
3431 pthread_mutex_unlock(&adev->lock);
3432 return 0;
3433}
3434
3435static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3436{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003437 int ret;
3438
3439 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003440 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003441 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3442 pthread_mutex_unlock(&adev->lock);
3443
3444 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445}
3446
3447static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3448{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003449 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 return 0;
3451}
3452
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003453static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 const struct audio_config *config)
3455{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003456 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003458 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3459 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460}
3461
3462static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003463 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 audio_devices_t devices,
3465 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003466 struct audio_stream_in **stream_in,
3467 audio_input_flags_t flags __unused,
3468 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003469 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470{
3471 struct audio_device *adev = (struct audio_device *)dev;
3472 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003473 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003474 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003475 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477 *stream_in = NULL;
3478 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3479 return -EINVAL;
3480
3481 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003482
3483 if (!in) {
3484 ALOGE("failed to allocate input stream");
3485 return -ENOMEM;
3486 }
3487
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303488 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003489 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3490 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003492 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07003493 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495 in->stream.common.get_sample_rate = in_get_sample_rate;
3496 in->stream.common.set_sample_rate = in_set_sample_rate;
3497 in->stream.common.get_buffer_size = in_get_buffer_size;
3498 in->stream.common.get_channels = in_get_channels;
3499 in->stream.common.get_format = in_get_format;
3500 in->stream.common.set_format = in_set_format;
3501 in->stream.common.standby = in_standby;
3502 in->stream.common.dump = in_dump;
3503 in->stream.common.set_parameters = in_set_parameters;
3504 in->stream.common.get_parameters = in_get_parameters;
3505 in->stream.common.add_audio_effect = in_add_audio_effect;
3506 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3507 in->stream.set_gain = in_set_gain;
3508 in->stream.read = in_read;
3509 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3510
3511 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003512 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 in->standby = 1;
3515 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003516 in->capture_handle = handle;
Naresh Tanniru4a080142015-06-15 10:35:19 -07003517 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518
3519 /* Update config params with the requested sample rate and channels */
3520 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003521 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3522 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3523 is_low_latency = true;
3524#if LOW_LATENCY_CAPTURE_USE_CASE
3525 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3526#endif
3527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003530 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003532 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303533 if (adev->mode != AUDIO_MODE_IN_CALL) {
3534 ret = -EINVAL;
3535 goto err_open;
3536 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003537 if (config->sample_rate == 0)
3538 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3539 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3540 config->sample_rate != 8000) {
3541 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3542 ret = -EINVAL;
3543 goto err_open;
3544 }
3545 if (config->format == AUDIO_FORMAT_DEFAULT)
3546 config->format = AUDIO_FORMAT_PCM_16_BIT;
3547 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3548 config->format = AUDIO_FORMAT_PCM_16_BIT;
3549 ret = -EINVAL;
3550 goto err_open;
3551 }
3552
3553 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3554 in->config = pcm_config_afe_proxy_record;
3555 in->config.channels = channel_count;
3556 in->config.rate = config->sample_rate;
3557 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003558 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003559 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003560 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3561 ret = -EINVAL;
3562 goto err_open;
3563 }
3564 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003565 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003566 }
Mingming Yine62d7842013-10-25 16:26:03 -07003567 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003568 audio_extn_compr_cap_format_supported(config->format) &&
3569 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003570 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003571 } else {
3572 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003573 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003574 buffer_size = get_input_buffer_size(config->sample_rate,
3575 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003576 channel_count,
3577 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003578 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003579 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3580 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3581 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3582 (in->config.rate == 8000 || in->config.rate == 16000) &&
3583 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3584 voice_extn_compress_voip_open_input_stream(in);
3585 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003588 /* This stream could be for sound trigger lab,
3589 get sound trigger pcm if present */
3590 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303591 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003594 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003595 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596
3597err_open:
3598 free(in);
3599 *stream_in = NULL;
3600 return ret;
3601}
3602
3603static void adev_close_input_stream(struct audio_hw_device *dev,
3604 struct audio_stream_in *stream)
3605{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003606 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003607 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003608 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303609
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303610 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003611
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303612 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003613 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303614
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003615 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303616 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003617 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303618 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003619 if (ret != 0)
3620 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3621 __func__, ret);
3622 } else
3623 in_standby(&stream->common);
3624
Mingming Yin7b762e72015-03-04 13:47:32 -08003625 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003626 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003627 audio_extn_ssr_deinit();
3628 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
Mingming Yine62d7842013-10-25 16:26:03 -07003630 if(audio_extn_compr_cap_enabled() &&
3631 audio_extn_compr_cap_format_supported(in->config.format))
3632 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003633
3634 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 return;
3636}
3637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003638static int adev_dump(const audio_hw_device_t *device __unused,
3639 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640{
3641 return 0;
3642}
3643
3644static int adev_close(hw_device_t *device)
3645{
3646 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003647
3648 if (!adev)
3649 return 0;
3650
3651 pthread_mutex_lock(&adev_init_lock);
3652
3653 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003654 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003655 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003656 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003657 audio_route_free(adev->audio_route);
3658 free(adev->snd_dev_ref_cnt);
3659 platform_deinit(adev->platform);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003660 if (adev->adm_deinit)
3661 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003662 free(device);
3663 adev = NULL;
3664 }
3665 pthread_mutex_unlock(&adev_init_lock);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 return 0;
3668}
3669
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003670/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3671 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3672 * just that it _might_ work.
3673 */
3674static int period_size_is_plausible_for_low_latency(int period_size)
3675{
3676 switch (period_size) {
3677 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003678 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003679 case 240:
3680 case 320:
3681 case 480:
3682 return 1;
3683 default:
3684 return 0;
3685 }
3686}
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688static int adev_open(const hw_module_t *module, const char *name,
3689 hw_device_t **device)
3690{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003691 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003693 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3695
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003696 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003697 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003698 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003699 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003700 ALOGD("%s: returning existing instance of adev", __func__);
3701 ALOGD("%s: exit", __func__);
3702 pthread_mutex_unlock(&adev_init_lock);
3703 return 0;
3704 }
3705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 adev = calloc(1, sizeof(struct audio_device));
3707
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003708 if (!adev) {
3709 pthread_mutex_unlock(&adev_init_lock);
3710 return -ENOMEM;
3711 }
3712
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003713 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3716 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3717 adev->device.common.module = (struct hw_module_t *)module;
3718 adev->device.common.close = adev_close;
3719
3720 adev->device.init_check = adev_init_check;
3721 adev->device.set_voice_volume = adev_set_voice_volume;
3722 adev->device.set_master_volume = adev_set_master_volume;
3723 adev->device.get_master_volume = adev_get_master_volume;
3724 adev->device.set_master_mute = adev_set_master_mute;
3725 adev->device.get_master_mute = adev_get_master_mute;
3726 adev->device.set_mode = adev_set_mode;
3727 adev->device.set_mic_mute = adev_set_mic_mute;
3728 adev->device.get_mic_mute = adev_get_mic_mute;
3729 adev->device.set_parameters = adev_set_parameters;
3730 adev->device.get_parameters = adev_get_parameters;
3731 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3732 adev->device.open_output_stream = adev_open_output_stream;
3733 adev->device.close_output_stream = adev_close_output_stream;
3734 adev->device.open_input_stream = adev_open_input_stream;
3735 adev->device.close_input_stream = adev_close_input_stream;
3736 adev->device.dump = adev_dump;
3737
3738 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003740 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003741 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003744 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003745 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003746 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003747 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003748 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003749 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003750 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303751 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303752
3753 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3754 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003756 adev->platform = platform_init(adev);
3757 if (!adev->platform) {
3758 free(adev->snd_dev_ref_cnt);
3759 free(adev);
3760 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3761 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003762 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003763 return -EINVAL;
3764 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003765
Naresh Tanniru4c630392014-05-12 01:05:52 +05303766 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3767
Eric Laurentc4aef752013-09-12 17:45:53 -07003768 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3769 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3770 if (adev->visualizer_lib == NULL) {
3771 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3772 } else {
3773 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3774 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003775 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003776 "visualizer_hal_start_output");
3777 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003778 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003779 "visualizer_hal_stop_output");
3780 }
3781 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003782 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003783 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003784
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003785 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3786 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3787 if (adev->offload_effects_lib == NULL) {
3788 ALOGE("%s: DLOPEN failed for %s", __func__,
3789 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3790 } else {
3791 ALOGV("%s: DLOPEN successful for %s", __func__,
3792 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3793 adev->offload_effects_start_output =
3794 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3795 "offload_effects_bundle_hal_start_output");
3796 adev->offload_effects_stop_output =
3797 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3798 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003799 adev->offload_effects_set_hpx_state =
3800 (int (*)(bool))dlsym(adev->offload_effects_lib,
3801 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303802 adev->offload_effects_get_parameters =
3803 (void (*)(struct str_parms *, struct str_parms *))
3804 dlsym(adev->offload_effects_lib,
3805 "offload_effects_bundle_get_parameters");
3806 adev->offload_effects_set_parameters =
3807 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3808 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003809 }
3810 }
3811
Naresh Tanniru4a080142015-06-15 10:35:19 -07003812 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3813 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3814 if (adev->adm_lib == NULL) {
3815 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3816 } else {
3817 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3818 adev->adm_init = (adm_init_t)
3819 dlsym(adev->adm_lib, "adm_init");
3820 adev->adm_deinit = (adm_deinit_t)
3821 dlsym(adev->adm_lib, "adm_deinit");
3822 adev->adm_register_input_stream = (adm_register_input_stream_t)
3823 dlsym(adev->adm_lib, "adm_register_input_stream");
3824 adev->adm_register_output_stream = (adm_register_output_stream_t)
3825 dlsym(adev->adm_lib, "adm_register_output_stream");
3826 adev->adm_deregister_stream = (adm_deregister_stream_t)
3827 dlsym(adev->adm_lib, "adm_deregister_stream");
3828 adev->adm_request_focus = (adm_request_focus_t)
3829 dlsym(adev->adm_lib, "adm_request_focus");
3830 adev->adm_abandon_focus = (adm_abandon_focus_t)
3831 dlsym(adev->adm_lib, "adm_abandon_focus");
3832 }
3833 }
3834
Mingming Yin514a8bc2014-07-29 15:22:21 -07003835 adev->bt_wb_speech_enabled = false;
3836
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003837 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 *device = &adev->device.common;
3839
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003840 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3841 &adev->streams_output_cfg_list);
3842
Kiran Kandi910e1862013-10-29 13:29:42 -07003843 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003844
3845 char value[PROPERTY_VALUE_MAX];
3846 int trial;
3847 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3848 trial = atoi(value);
3849 if (period_size_is_plausible_for_low_latency(trial)) {
3850 pcm_config_low_latency.period_size = trial;
3851 pcm_config_low_latency.start_threshold = trial / 4;
3852 pcm_config_low_latency.avail_min = trial / 4;
3853 configured_low_latency_capture_period_size = trial;
3854 }
3855 }
3856 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3857 trial = atoi(value);
3858 if (period_size_is_plausible_for_low_latency(trial)) {
3859 configured_low_latency_capture_period_size = trial;
3860 }
3861 }
3862
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003863 pthread_mutex_unlock(&adev_init_lock);
3864
Naresh Tanniru4a080142015-06-15 10:35:19 -07003865 if (adev->adm_init)
3866 adev->adm_data = adev->adm_init();
3867
Eric Laurent994a6932013-07-17 11:51:42 -07003868 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 return 0;
3870}
3871
3872static struct hw_module_methods_t hal_module_methods = {
3873 .open = adev_open,
3874};
3875
3876struct audio_module HAL_MODULE_INFO_SYM = {
3877 .common = {
3878 .tag = HARDWARE_MODULE_TAG,
3879 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3880 .hal_api_version = HARDWARE_HAL_API_VERSION,
3881 .id = AUDIO_HARDWARE_MODULE_ID,
3882 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003883 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 .methods = &hal_module_methods,
3885 },
3886};