blob: 9447d7e8816d1f61605a4e3f7cbbb26fe083f239 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
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,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800453 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800475 strcpy(mixer_path, use_case_table[usecase->id]);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700508 if (audio_extn_spkr_prot_is_enabled())
509 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700510 /* start usb playback thread */
511 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
512 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
513 audio_extn_usb_start_playback(adev);
514
515 /* start usb capture thread */
516 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
517 audio_extn_usb_start_capture(adev);
518
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800519 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700520 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
521 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
522 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
523 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700524 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
525 adev->snd_dev_ref_cnt[snd_device]--;
526 return -EINVAL;
527 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200528 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800529 if (audio_extn_spkr_prot_start_processing(snd_device)) {
530 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200531 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800532 return -EINVAL;
533 }
534 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700535 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700536 /* due to the possibility of calibration overwrite between listen
537 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700538 audio_extn_sound_trigger_update_device_status(snd_device,
539 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530540 audio_extn_listen_update_device_status(snd_device,
541 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700542 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700543 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700544 audio_extn_sound_trigger_update_device_status(snd_device,
545 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530546 audio_extn_listen_update_device_status(snd_device,
547 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700548 return -EINVAL;
549 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300550 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700551 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800553 return 0;
554}
555
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700556int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700557 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700559 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
560
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800561 if (snd_device < SND_DEVICE_MIN ||
562 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800563 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800564 return -EINVAL;
565 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700566 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
567 ALOGE("%s: device ref cnt is already 0", __func__);
568 return -EINVAL;
569 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700570
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700572
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
574 ALOGE("%s: Invalid sound device returned", __func__);
575 return -EINVAL;
576 }
577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700579 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800580 /* exit usb play back thread */
581 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
582 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
583 audio_extn_usb_stop_playback();
584
585 /* exit usb capture thread */
586 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700587 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800588
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800589 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
Banajit Goswami20cdd212015-09-11 01:11:30 -0700590 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT ||
591 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
592 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
593 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700594 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300595 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700596 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300597 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700598
Ashish Jain81eb2a82015-05-13 10:52:34 +0530599 if (snd_device == SND_DEVICE_OUT_HDMI)
600 adev->is_channel_status_set = false;
601
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200602 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603 audio_extn_sound_trigger_update_device_status(snd_device,
604 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530605 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800606 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609 return 0;
610}
611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612static void check_usecases_codec_backend(struct audio_device *adev,
613 struct audio_usecase *uc_info,
614 snd_device_t snd_device)
615{
616 struct listnode *node;
617 struct audio_usecase *usecase;
618 bool switch_device[AUDIO_USECASE_MAX];
619 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800620 int backend_idx = DEFAULT_CODEC_BACKEND;
621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622
623 /*
624 * This function is to make sure that all the usecases that are active on
625 * the hardware codec backend are always routed to any one device that is
626 * handled by the hardware codec.
627 * For example, if low-latency and deep-buffer usecases are currently active
628 * on speaker and out_set_parameters(headset) is received on low-latency
629 * output, then we have to make sure deep-buffer is also switched to headset,
630 * because of the limitation that both the devices cannot be enabled
631 * at the same time as they share the same backend.
632 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700633 /*
634 * This call is to check if we need to force routing for a particular stream
635 * If there is a backend configuration change for the device when a
636 * new stream starts, then ADM needs to be closed and re-opened with the new
637 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800638 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700639 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800640 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
641 snd_device);
642 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800644 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800645 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 for (i = 0; i < AUDIO_USECASE_MAX; i++)
647 switch_device[i] = false;
648
649 list_for_each(node, &adev->usecase_list) {
650 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651
652 if (usecase == uc_info)
653 continue;
654 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
655 ALOGV("%s: backend_idx: %d,"
656 "usecase_backend_idx: %d, curr device: %s, usecase device:"
657 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530658 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800659
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800660 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700661 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800662 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
663 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530664 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800665 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700666 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700667 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 switch_device[usecase->id] = true;
669 num_uc_to_switch++;
670 }
671 }
672
673 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700674 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530676 /* Make sure the previous devices to be disabled first and then enable the
677 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 list_for_each(node, &adev->usecase_list) {
679 usecase = node_to_item(node, struct audio_usecase, list);
680 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700681 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700682 }
683 }
684
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700685 list_for_each(node, &adev->usecase_list) {
686 usecase = node_to_item(node, struct audio_usecase, list);
687 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700688 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700689 }
690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700692 /* Re-route all the usecases on the shared backend other than the
693 specified usecase to new snd devices */
694 list_for_each(node, &adev->usecase_list) {
695 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530696 /* Update the out_snd_device only for the usecases that are enabled here */
697 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
698 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530699 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700700 }
701 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702 }
703}
704
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700705static void check_and_route_capture_usecases(struct audio_device *adev,
706 struct audio_usecase *uc_info,
707 snd_device_t snd_device)
708{
709 struct listnode *node;
710 struct audio_usecase *usecase;
711 bool switch_device[AUDIO_USECASE_MAX];
712 int i, num_uc_to_switch = 0;
713
714 /*
715 * This function is to make sure that all the active capture usecases
716 * are always routed to the same input sound device.
717 * For example, if audio-record and voice-call usecases are currently
718 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
719 * is received for voice call then we have to make sure that audio-record
720 * usecase is also switched to earpiece i.e. voice-dmic-ef,
721 * because of the limitation that two devices cannot be enabled
722 * at the same time if they share the same backend.
723 */
724 for (i = 0; i < AUDIO_USECASE_MAX; i++)
725 switch_device[i] = false;
726
727 list_for_each(node, &adev->usecase_list) {
728 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800729 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700730 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700731 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700732 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
733 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700734 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
736 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700737 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700738 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 switch_device[usecase->id] = true;
740 num_uc_to_switch++;
741 }
742 }
743
744 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700745 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700746
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530747 /* Make sure the previous devices to be disabled first and then enable the
748 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700749 list_for_each(node, &adev->usecase_list) {
750 usecase = node_to_item(node, struct audio_usecase, list);
751 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700752 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800753 }
754 }
755
756 list_for_each(node, &adev->usecase_list) {
757 usecase = node_to_item(node, struct audio_usecase, list);
758 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 }
761 }
762
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 /* Re-route all the usecases on the shared backend other than the
764 specified usecase to new snd devices */
765 list_for_each(node, &adev->usecase_list) {
766 usecase = node_to_item(node, struct audio_usecase, list);
767 /* Update the in_snd_device only before enabling the audio route */
768 if (switch_device[usecase->id] ) {
769 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800770 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530771 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700772 }
773 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 }
775}
776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700778static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700780 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700781 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782
783 switch (channels) {
784 /*
785 * Do not handle stereo output in Multi-channel cases
786 * Stereo case is handled in normal playback path
787 */
788 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700789 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
794 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800795 break;
796 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700797 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
799 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
801 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
802 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
803 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804 break;
805 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700806 ALOGE("HDMI does not support multi channel playback");
807 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 break;
809 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700810 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800811}
812
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800813audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
814 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815{
816 struct audio_usecase *usecase;
817 struct listnode *node;
818
819 list_for_each(node, &adev->usecase_list) {
820 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800821 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700822 ALOGV("%s: usecase id %d", __func__, usecase->id);
823 return usecase->id;
824 }
825 }
826 return USECASE_INVALID;
827}
828
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700829struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700830 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831{
832 struct audio_usecase *usecase;
833 struct listnode *node;
834
835 list_for_each(node, &adev->usecase_list) {
836 usecase = node_to_item(node, struct audio_usecase, list);
837 if (usecase->id == uc_id)
838 return usecase;
839 }
840 return NULL;
841}
842
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700843int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800845 snd_device_t out_snd_device = SND_DEVICE_NONE;
846 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 struct audio_usecase *usecase = NULL;
848 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800850 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800851 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800852 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 usecase = get_usecase_from_list(adev, uc_id);
856 if (usecase == NULL) {
857 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
858 return -EINVAL;
859 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800861 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800862 (usecase->type == VOIP_CALL) ||
863 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700864 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800865 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 usecase->devices = usecase->stream.out->devices;
868 } else {
869 /*
870 * If the voice call is active, use the sound devices of voice call usecase
871 * so that it would not result any device switch. All the usecases will
872 * be switched to new device when select_devices() is called for voice call
873 * usecase. This is to avoid switching devices for voice call when
874 * check_usecases_codec_backend() is called below.
875 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700876 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700877 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800878 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700879 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
880 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 in_snd_device = vc_usecase->in_snd_device;
882 out_snd_device = vc_usecase->out_snd_device;
883 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800884 } else if (voice_extn_compress_voip_is_active(adev)) {
885 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700886 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530887 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700888 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800889 in_snd_device = voip_usecase->in_snd_device;
890 out_snd_device = voip_usecase->out_snd_device;
891 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800892 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800893 hfp_ucid = audio_extn_hfp_get_usecase();
894 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700895 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800896 in_snd_device = hfp_usecase->in_snd_device;
897 out_snd_device = hfp_usecase->out_snd_device;
898 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 if (usecase->type == PCM_PLAYBACK) {
901 usecase->devices = usecase->stream.out->devices;
902 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700904 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800905 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700906 if (usecase->stream.out == adev->primary_output &&
907 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800908 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700909 select_devices(adev, adev->active_input->usecase);
910 }
911 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912 } else if (usecase->type == PCM_CAPTURE) {
913 usecase->devices = usecase->stream.in->device;
914 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700916 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530917 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
918 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
919 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
920 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700921 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700922 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700923 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
924 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700925 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700926 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700927 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928 }
929 }
930
931 if (out_snd_device == usecase->out_snd_device &&
932 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 return 0;
934 }
935
sangwoobc677242013-08-08 16:53:43 +0900936 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700937 out_snd_device, platform_get_snd_device_name(out_snd_device),
938 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800940 /*
941 * Limitation: While in call, to do a device switch we need to disable
942 * and enable both RX and TX devices though one of them is same as current
943 * device.
944 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700945 if ((usecase->type == VOICE_CALL) &&
946 (usecase->in_snd_device != SND_DEVICE_NONE) &&
947 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700948 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700949 }
950
951 if (((usecase->type == VOICE_CALL) ||
952 (usecase->type == VOIP_CALL)) &&
953 (usecase->out_snd_device != SND_DEVICE_NONE)) {
954 /* Disable sidetone only if voice/voip call already exists */
955 if (voice_is_call_state_active(adev) ||
956 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700957 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800958 }
959
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 /* Disable current sound devices */
961 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700962 disable_audio_route(adev, usecase);
963 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964 }
965
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700967 disable_audio_route(adev, usecase);
968 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969 }
970
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800971 /* Applicable only on the targets that has external modem.
972 * New device information should be sent to modem before enabling
973 * the devices to reduce in-call device switch time.
974 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700975 if ((usecase->type == VOICE_CALL) &&
976 (usecase->in_snd_device != SND_DEVICE_NONE) &&
977 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800978 status = platform_switch_voice_call_enable_device_config(adev->platform,
979 out_snd_device,
980 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700981 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800982
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700983 /* Enable new sound devices */
984 if (out_snd_device != SND_DEVICE_NONE) {
985 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
986 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700987 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988 }
989
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 if (in_snd_device != SND_DEVICE_NONE) {
991 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700992 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994
Avinash Vaish71a8b972014-07-24 15:36:33 +0530995 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700996 status = platform_switch_voice_call_device_post(adev->platform,
997 out_snd_device,
998 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530999 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001000 /* Enable sidetone only if voice/voip call already exists */
1001 if (voice_is_call_state_active(adev) ||
1002 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001003 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301004 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001005
sangwoo170731f2013-06-08 15:36:36 +09001006 usecase->in_snd_device = in_snd_device;
1007 usecase->out_snd_device = out_snd_device;
1008
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301009 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001010 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301011 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001012 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301013 usecase->stream.out->flags,
1014 usecase->stream.out->format,
1015 usecase->stream.out->sample_rate,
1016 usecase->stream.out->bit_width,
1017 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001018 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301019 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001020
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001021 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001022
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001023 /* Applicable only on the targets that has external modem.
1024 * Enable device command should be sent to modem only after
1025 * enabling voice call mixer controls
1026 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001027 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001028 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1029 out_snd_device,
1030 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301031 ALOGD("%s: done",__func__);
1032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 return status;
1034}
1035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036static int stop_input_stream(struct stream_in *in)
1037{
1038 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 struct audio_usecase *uc_info;
1040 struct audio_device *adev = in->dev;
1041
Eric Laurentc8400632013-02-14 19:04:54 -08001042 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043
Eric Laurent994a6932013-07-17 11:51:42 -07001044 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001045 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 uc_info = get_usecase_from_list(adev, in->usecase);
1047 if (uc_info == NULL) {
1048 ALOGE("%s: Could not find the usecase (%d) in the list",
1049 __func__, in->usecase);
1050 return -EINVAL;
1051 }
1052
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001053 /* Close in-call recording streams */
1054 voice_check_and_stop_incall_rec_usecase(adev, in);
1055
Eric Laurent150dbfe2013-02-27 14:31:02 -08001056 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001057 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058
1059 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001060 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001062 list_remove(&uc_info->list);
1063 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
Eric Laurent994a6932013-07-17 11:51:42 -07001065 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 return ret;
1067}
1068
1069int start_input_stream(struct stream_in *in)
1070{
1071 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001072 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001073 struct audio_usecase *uc_info;
1074 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301075 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076
Mingming Yin2664a5b2015-09-03 10:53:11 -07001077 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1078 if (get_usecase_from_list(adev, usecase) == NULL)
1079 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301080 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1081 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001082
Naresh Tanniru80659832014-06-04 18:17:56 +05301083
1084 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301085 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301086 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087 goto error_config;
1088 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001090 /* Check if source matches incall recording usecase criteria */
1091 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1092 if (ret)
1093 goto error_config;
1094 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001095 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1096
1097 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1098 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1099 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1100 goto error_config;
1101 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001102
Eric Laurentb23d5282013-05-14 15:27:20 -07001103 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 if (in->pcm_device_id < 0) {
1105 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1106 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001107 ret = -EINVAL;
1108 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001110
1111 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001113
1114 if (!uc_info) {
1115 ret = -ENOMEM;
1116 goto error_config;
1117 }
1118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119 uc_info->id = in->usecase;
1120 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001121 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 uc_info->devices = in->device;
1123 uc_info->in_snd_device = SND_DEVICE_NONE;
1124 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001126 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301127 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1128 adev->perf_lock_opts,
1129 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131
Eric Laurentc8400632013-02-14 19:04:54 -08001132 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001133 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1134
1135 unsigned int flags = PCM_IN;
1136 unsigned int pcm_open_retry_count = 0;
1137
1138 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1139 flags |= PCM_MMAP | PCM_NOIRQ;
1140 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1141 }
1142
1143 while (1) {
1144 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1145 flags, &in->config);
1146 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1147 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1148 if (in->pcm != NULL) {
1149 pcm_close(in->pcm);
1150 in->pcm = NULL;
1151 }
1152 if (pcm_open_retry_count-- == 0) {
1153 ret = -EIO;
1154 goto error_open;
1155 }
1156 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1157 continue;
1158 }
1159 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001160 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001161
1162 ALOGV("%s: pcm_prepare", __func__);
1163 ret = pcm_prepare(in->pcm);
1164 if (ret < 0) {
1165 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1166 pcm_close(in->pcm);
1167 in->pcm = NULL;
1168 goto error_open;
1169 }
1170
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301171 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001172 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001173
Eric Laurentc8400632013-02-14 19:04:54 -08001174 return ret;
1175
1176error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301177 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001178 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001179error_config:
1180 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301181 /*
1182 * sleep 50ms to allow sufficient time for kernel
1183 * drivers to recover incases like SSR.
1184 */
1185 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001187
1188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001189}
1190
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001191void lock_input_stream(struct stream_in *in)
1192{
1193 pthread_mutex_lock(&in->pre_lock);
1194 pthread_mutex_lock(&in->lock);
1195 pthread_mutex_unlock(&in->pre_lock);
1196}
1197
1198void lock_output_stream(struct stream_out *out)
1199{
1200 pthread_mutex_lock(&out->pre_lock);
1201 pthread_mutex_lock(&out->lock);
1202 pthread_mutex_unlock(&out->pre_lock);
1203}
1204
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001205/* must be called with out->lock locked */
1206static int send_offload_cmd_l(struct stream_out* out, int command)
1207{
1208 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1209
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001210 if (!cmd) {
1211 ALOGE("failed to allocate mem for command 0x%x", command);
1212 return -ENOMEM;
1213 }
1214
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215 ALOGVV("%s %d", __func__, command);
1216
1217 cmd->cmd = command;
1218 list_add_tail(&out->offload_cmd_list, &cmd->node);
1219 pthread_cond_signal(&out->offload_cond);
1220 return 0;
1221}
1222
1223/* must be called iwth out->lock locked */
1224static void stop_compressed_output_l(struct stream_out *out)
1225{
1226 out->offload_state = OFFLOAD_STATE_IDLE;
1227 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001228 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001229 if (out->compr != NULL) {
1230 compress_stop(out->compr);
1231 while (out->offload_thread_blocked) {
1232 pthread_cond_wait(&out->cond, &out->lock);
1233 }
1234 }
1235}
1236
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001237bool is_offload_usecase(audio_usecase_t uc_id)
1238{
1239 unsigned int i;
1240 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1241 if (uc_id == offload_usecases[i])
1242 return true;
1243 }
1244 return false;
1245}
1246
vivek mehta446c3962015-09-14 10:57:35 -07001247static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001248{
vivek mehta446c3962015-09-14 10:57:35 -07001249 audio_usecase_t ret_uc = USECASE_INVALID;
1250 unsigned int offload_uc_index;
1251 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1252 if (!adev->multi_offload_enable) {
1253 if (is_direct_pcm)
1254 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1255 else
1256 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001257
vivek mehta446c3962015-09-14 10:57:35 -07001258 pthread_mutex_lock(&adev->lock);
1259 if (get_usecase_from_list(adev, ret_uc) != NULL)
1260 ret_uc = USECASE_INVALID;
1261 pthread_mutex_unlock(&adev->lock);
1262
1263 return ret_uc;
1264 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001265
1266 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001267 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1268 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1269 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1270 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001271 break;
1272 }
1273 }
vivek mehta446c3962015-09-14 10:57:35 -07001274
1275 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1276 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001277}
1278
1279static void free_offload_usecase(struct audio_device *adev,
1280 audio_usecase_t uc_id)
1281{
vivek mehta446c3962015-09-14 10:57:35 -07001282 unsigned int offload_uc_index;
1283 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1284
1285 if (!adev->multi_offload_enable)
1286 return;
1287
1288 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1289 if (offload_usecases[offload_uc_index] == uc_id) {
1290 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001291 break;
1292 }
1293 }
1294 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1295}
1296
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001297static void *offload_thread_loop(void *context)
1298{
1299 struct stream_out *out = (struct stream_out *) context;
1300 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001301 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001302
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001303 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1304 set_sched_policy(0, SP_FOREGROUND);
1305 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1306
1307 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001308 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001309 for (;;) {
1310 struct offload_cmd *cmd = NULL;
1311 stream_callback_event_t event;
1312 bool send_callback = false;
1313
1314 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1315 __func__, list_empty(&out->offload_cmd_list),
1316 out->offload_state);
1317 if (list_empty(&out->offload_cmd_list)) {
1318 ALOGV("%s SLEEPING", __func__);
1319 pthread_cond_wait(&out->offload_cond, &out->lock);
1320 ALOGV("%s RUNNING", __func__);
1321 continue;
1322 }
1323
1324 item = list_head(&out->offload_cmd_list);
1325 cmd = node_to_item(item, struct offload_cmd, node);
1326 list_remove(item);
1327
1328 ALOGVV("%s STATE %d CMD %d out->compr %p",
1329 __func__, out->offload_state, cmd->cmd, out->compr);
1330
1331 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1332 free(cmd);
1333 break;
1334 }
1335
1336 if (out->compr == NULL) {
1337 ALOGE("%s: Compress handle is NULL", __func__);
1338 pthread_cond_signal(&out->cond);
1339 continue;
1340 }
1341 out->offload_thread_blocked = true;
1342 pthread_mutex_unlock(&out->lock);
1343 send_callback = false;
1344 switch(cmd->cmd) {
1345 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001346 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001348 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001349 send_callback = true;
1350 event = STREAM_CBK_EVENT_WRITE_READY;
1351 break;
1352 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001353 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301354 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001355 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301356 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001357 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301358 if (ret < 0)
1359 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301360 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301361 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001362 compress_drain(out->compr);
1363 else
1364 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301365 if (ret != -ENETRESET) {
1366 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301367 pthread_mutex_lock(&out->lock);
1368 out->send_new_metadata = 1;
1369 out->send_next_track_params = true;
1370 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301371 event = STREAM_CBK_EVENT_DRAIN_READY;
1372 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1373 } else
1374 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001375 break;
1376 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001377 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001378 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001379 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 send_callback = true;
1381 event = STREAM_CBK_EVENT_DRAIN_READY;
1382 break;
1383 default:
1384 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1385 break;
1386 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001387 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001388 out->offload_thread_blocked = false;
1389 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001390 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001391 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001393 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001394 free(cmd);
1395 }
1396
1397 pthread_cond_signal(&out->cond);
1398 while (!list_empty(&out->offload_cmd_list)) {
1399 item = list_head(&out->offload_cmd_list);
1400 list_remove(item);
1401 free(node_to_item(item, struct offload_cmd, node));
1402 }
1403 pthread_mutex_unlock(&out->lock);
1404
1405 return NULL;
1406}
1407
1408static int create_offload_callback_thread(struct stream_out *out)
1409{
1410 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1411 list_init(&out->offload_cmd_list);
1412 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1413 offload_thread_loop, out);
1414 return 0;
1415}
1416
1417static int destroy_offload_callback_thread(struct stream_out *out)
1418{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001419 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001420 stop_compressed_output_l(out);
1421 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1422
1423 pthread_mutex_unlock(&out->lock);
1424 pthread_join(out->offload_thread, (void **) NULL);
1425 pthread_cond_destroy(&out->offload_cond);
1426
1427 return 0;
1428}
1429
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430static bool allow_hdmi_channel_config(struct audio_device *adev)
1431{
1432 struct listnode *node;
1433 struct audio_usecase *usecase;
1434 bool ret = true;
1435
1436 list_for_each(node, &adev->usecase_list) {
1437 usecase = node_to_item(node, struct audio_usecase, list);
1438 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1439 /*
1440 * If voice call is already existing, do not proceed further to avoid
1441 * disabling/enabling both RX and TX devices, CSD calls, etc.
1442 * Once the voice call done, the HDMI channels can be configured to
1443 * max channels of remaining use cases.
1444 */
1445 if (usecase->id == USECASE_VOICE_CALL) {
1446 ALOGD("%s: voice call is active, no change in HDMI channels",
1447 __func__);
1448 ret = false;
1449 break;
1450 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1451 ALOGD("%s: multi channel playback is active, "
1452 "no change in HDMI channels", __func__);
1453 ret = false;
1454 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001455 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001456 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001457 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1458 ", no change in HDMI channels", __func__,
1459 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001460 ret = false;
1461 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001462 }
1463 }
1464 }
1465 return ret;
1466}
1467
1468static int check_and_set_hdmi_channels(struct audio_device *adev,
1469 unsigned int channels)
1470{
1471 struct listnode *node;
1472 struct audio_usecase *usecase;
1473
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001474 unsigned int supported_channels = platform_edid_get_max_channels(
1475 adev->platform);
1476 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001477 /* Check if change in HDMI channel config is allowed */
1478 if (!allow_hdmi_channel_config(adev))
1479 return 0;
1480
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001481 if (channels > supported_channels)
1482 channels = supported_channels;
1483
Eric Laurent07eeafd2013-10-06 12:52:49 -07001484 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001485 ALOGD("%s: Requested channels are same as current channels(%d)",
1486 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001487 return 0;
1488 }
1489
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001490 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001491 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001492 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001493 adev->cur_hdmi_channels = channels;
1494
1495 /*
1496 * Deroute all the playback streams routed to HDMI so that
1497 * the back end is deactivated. Note that backend will not
1498 * be deactivated if any one stream is connected to it.
1499 */
1500 list_for_each(node, &adev->usecase_list) {
1501 usecase = node_to_item(node, struct audio_usecase, list);
1502 if (usecase->type == PCM_PLAYBACK &&
1503 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001504 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001505 }
1506 }
1507
1508 /*
1509 * Enable all the streams disabled above. Now the HDMI backend
1510 * will be activated with new channel configuration
1511 */
1512 list_for_each(node, &adev->usecase_list) {
1513 usecase = node_to_item(node, struct audio_usecase, list);
1514 if (usecase->type == PCM_PLAYBACK &&
1515 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001516 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001517 }
1518 }
1519
1520 return 0;
1521}
1522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523static int stop_output_stream(struct stream_out *out)
1524{
1525 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 struct audio_usecase *uc_info;
1527 struct audio_device *adev = out->dev;
1528
Eric Laurent994a6932013-07-17 11:51:42 -07001529 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 uc_info = get_usecase_from_list(adev, out->usecase);
1532 if (uc_info == NULL) {
1533 ALOGE("%s: Could not find the usecase (%d) in the list",
1534 __func__, out->usecase);
1535 return -EINVAL;
1536 }
1537
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001538 if (is_offload_usecase(out->usecase) &&
1539 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001540 if (adev->visualizer_stop_output != NULL)
1541 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001542
1543 audio_extn_dts_remove_state_notifier_node(out->usecase);
1544
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001545 if (adev->offload_effects_stop_output != NULL)
1546 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1547 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001548
Eric Laurent150dbfe2013-02-27 14:31:02 -08001549 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001550 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001551
1552 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001553 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001555 list_remove(&uc_info->list);
1556 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001557
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001558 if (is_offload_usecase(out->usecase) &&
1559 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1560 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1561 ALOGV("Disable passthrough , reset mixer to pcm");
1562 /* NO_PASSTHROUGH */
1563 out->compr_config.codec->compr_passthr = 0;
1564 audio_extn_dolby_set_hdmi_config(adev, out);
1565 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1566 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001567 /* Must be called after removing the usecase from list */
1568 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1569 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1570
Eric Laurent994a6932013-07-17 11:51:42 -07001571 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 return ret;
1573}
1574
1575int start_output_stream(struct stream_out *out)
1576{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001578 int sink_channels = 0;
1579 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580 struct audio_usecase *uc_info;
1581 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301582 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001584 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1585 ret = -EINVAL;
1586 goto error_config;
1587 }
1588
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301589 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1590 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1591 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301592
Naresh Tanniru80659832014-06-04 18:17:56 +05301593 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301594 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301595 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301596 goto error_config;
1597 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301598
Eric Laurentb23d5282013-05-14 15:27:20 -07001599 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600 if (out->pcm_device_id < 0) {
1601 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1602 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001603 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001604 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 }
1606
1607 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001608
1609 if (!uc_info) {
1610 ret = -ENOMEM;
1611 goto error_config;
1612 }
1613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 uc_info->id = out->usecase;
1615 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001616 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001617 uc_info->devices = out->devices;
1618 uc_info->in_snd_device = SND_DEVICE_NONE;
1619 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001620 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001621 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001622 if (is_offload_usecase(out->usecase)) {
1623 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001624 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1625 }
1626 }
Mingming Yin9c041392014-05-01 15:37:31 -07001627 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1628 if (!strncmp("true", prop_value, 4)) {
1629 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001630 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1631 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001632 check_and_set_hdmi_channels(adev, sink_channels);
1633 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001634 if (is_offload_usecase(out->usecase)) {
1635 unsigned int ch_count = out->compr_config.codec->ch_in;
1636 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1637 /* backend channel config for passthrough stream is stereo */
1638 ch_count = 2;
1639 check_and_set_hdmi_channels(adev, ch_count);
1640 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001641 check_and_set_hdmi_channels(adev, out->config.channels);
1642 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001643 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001644 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001645 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301647 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1648 adev->perf_lock_opts,
1649 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001650 select_devices(adev, out->usecase);
1651
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001652 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1653 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001654 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001655 unsigned int flags = PCM_OUT;
1656 unsigned int pcm_open_retry_count = 0;
1657 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1658 flags |= PCM_MMAP | PCM_NOIRQ;
1659 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1660 } else
1661 flags |= PCM_MONOTONIC;
1662
1663 while (1) {
1664 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1665 flags, &out->config);
1666 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1667 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1668 if (out->pcm != NULL) {
1669 pcm_close(out->pcm);
1670 out->pcm = NULL;
1671 }
1672 if (pcm_open_retry_count-- == 0) {
1673 ret = -EIO;
1674 goto error_open;
1675 }
1676 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1677 continue;
1678 }
1679 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001681
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001682 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1683 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001684
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001685 ALOGV("%s: pcm_prepare", __func__);
1686 if (pcm_is_ready(out->pcm)) {
1687 ret = pcm_prepare(out->pcm);
1688 if (ret < 0) {
1689 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1690 pcm_close(out->pcm);
1691 out->pcm = NULL;
1692 goto error_open;
1693 }
1694 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001695 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001696 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1697 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001699 out->compr = compress_open(adev->snd_card,
1700 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001701 COMPRESS_IN, &out->compr_config);
1702 if (out->compr && !is_compress_ready(out->compr)) {
1703 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1704 compress_close(out->compr);
1705 out->compr = NULL;
1706 ret = -EIO;
1707 goto error_open;
1708 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301709 /* compress_open sends params of the track, so reset the flag here */
1710 out->is_compr_metadata_avail = false;
1711
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001712 if (out->offload_callback)
1713 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001714
Fred Oh3f43e742015-03-04 18:42:34 -08001715 /* Since small bufs uses blocking writes, a write will be blocked
1716 for the default max poll time (20s) in the event of an SSR.
1717 Reduce the poll time to observe and deal with SSR faster.
1718 */
1719 if (out->use_small_bufs) {
1720 compress_set_max_poll_wait(out->compr, 1000);
1721 }
1722
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001723 audio_extn_dts_create_state_notifier_node(out->usecase);
1724 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1725 popcount(out->channel_mask),
1726 out->playback_started);
1727
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001728#ifdef DS1_DOLBY_DDP_ENABLED
1729 if (audio_extn_is_dolby_format(out->format))
1730 audio_extn_dolby_send_ddp_endp_params(adev);
1731#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001732 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1733 if (adev->visualizer_start_output != NULL)
1734 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1735 if (adev->offload_effects_start_output != NULL)
1736 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001737 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301740 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001741 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001744error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301745 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001747error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301748 /*
1749 * sleep 50ms to allow sufficient time for kernel
1750 * drivers to recover incases like SSR.
1751 */
1752 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001753 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754}
1755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756static int check_input_parameters(uint32_t sample_rate,
1757 audio_format_t format,
1758 int channel_count)
1759{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001760 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001763 !voice_extn_compress_voip_is_format_supported(format) &&
1764 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001765
1766 switch (channel_count) {
1767 case 1:
1768 case 2:
1769 case 6:
1770 break;
1771 default:
1772 ret = -EINVAL;
1773 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
1775 switch (sample_rate) {
1776 case 8000:
1777 case 11025:
1778 case 12000:
1779 case 16000:
1780 case 22050:
1781 case 24000:
1782 case 32000:
1783 case 44100:
1784 case 48000:
1785 break;
1786 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001787 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 }
1789
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001790 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791}
1792
1793static size_t get_input_buffer_size(uint32_t sample_rate,
1794 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001795 int channel_count,
1796 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797{
1798 size_t size = 0;
1799
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001800 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1801 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001803 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001804 if (is_low_latency)
1805 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001806 /* ToDo: should use frame_size computed based on the format and
1807 channel_count here. */
1808 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001810 /* make sure the size is multiple of 32 bytes
1811 * At 48 kHz mono 16-bit PCM:
1812 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1813 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1814 */
1815 size += 0x1f;
1816 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001817
1818 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819}
1820
1821static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1822{
1823 struct stream_out *out = (struct stream_out *)stream;
1824
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826}
1827
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001828static int out_set_sample_rate(struct audio_stream *stream __unused,
1829 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830{
1831 return -ENOSYS;
1832}
1833
1834static size_t out_get_buffer_size(const struct audio_stream *stream)
1835{
1836 struct stream_out *out = (struct stream_out *)stream;
1837
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001838 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001840 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1841 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001842
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001843 return out->config.period_size *
1844 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845}
1846
1847static uint32_t out_get_channels(const struct audio_stream *stream)
1848{
1849 struct stream_out *out = (struct stream_out *)stream;
1850
1851 return out->channel_mask;
1852}
1853
1854static audio_format_t out_get_format(const struct audio_stream *stream)
1855{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 struct stream_out *out = (struct stream_out *)stream;
1857
1858 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859}
1860
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001861static int out_set_format(struct audio_stream *stream __unused,
1862 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863{
1864 return -ENOSYS;
1865}
1866
1867static int out_standby(struct audio_stream *stream)
1868{
1869 struct stream_out *out = (struct stream_out *)stream;
1870 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001871
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301872 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1873 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001874 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1875 /* Ignore standby in case of voip call because the voip output
1876 * stream is closed in adev_close_output_stream()
1877 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301878 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001879 return 0;
1880 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001882 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001884 if (adev->adm_deregister_stream)
1885 adev->adm_deregister_stream(adev->adm_data, out->handle);
1886
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001887 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001889 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890 if (out->pcm) {
1891 pcm_close(out->pcm);
1892 out->pcm = NULL;
1893 }
1894 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001895 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301897 out->send_next_track_params = false;
1898 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001899 out->gapless_mdata.encoder_delay = 0;
1900 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001901 if (out->compr != NULL) {
1902 compress_close(out->compr);
1903 out->compr = NULL;
1904 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001905 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001907 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 }
1909 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001910 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 return 0;
1912}
1913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001914static int out_dump(const struct audio_stream *stream __unused,
1915 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916{
1917 return 0;
1918}
1919
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001920static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1921{
1922 int ret = 0;
1923 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001924
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001925 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001926 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001927 return -EINVAL;
1928 }
1929
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301930 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001931
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001932 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1933 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301934 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001935 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1937 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301938 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001939 }
1940
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001941 ALOGV("%s new encoder delay %u and padding %u", __func__,
1942 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1943
1944 return 0;
1945}
1946
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001947static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1948{
1949 return out == adev->primary_output || out == adev->voice_tx_output;
1950}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1953{
1954 struct stream_out *out = (struct stream_out *)stream;
1955 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001956 struct audio_usecase *usecase;
1957 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 struct str_parms *parms;
1959 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001960 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001961 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962
sangwoobc677242013-08-08 16:53:43 +09001963 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301966 if (!parms)
1967 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001968 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1969 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001971 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001972 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001974 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301975 * When HDMI cable is unplugged/usb hs is disconnected the
1976 * music playback is paused and the policy manager sends routing=0
1977 * But the audioflingercontinues to write data until standby time
1978 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979 * Avoid this by routing audio to speaker until standby.
1980 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301981 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1982 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001983 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001984 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1985 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986 }
1987
1988 /*
1989 * select_devices() call below switches all the usecases on the same
1990 * backend to the new device. Refer to check_usecases_codec_backend() in
1991 * the select_devices(). But how do we undo this?
1992 *
1993 * For example, music playback is active on headset (deep-buffer usecase)
1994 * and if we go to ringtones and select a ringtone, low-latency usecase
1995 * will be started on headset+speaker. As we can't enable headset+speaker
1996 * and headset devices at the same time, select_devices() switches the music
1997 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1998 * So when the ringtone playback is completed, how do we undo the same?
1999 *
2000 * We are relying on the out_set_parameters() call on deep-buffer output,
2001 * once the ringtone playback is ended.
2002 * NOTE: We should not check if the current devices are same as new devices.
2003 * Because select_devices() must be called to switch back the music
2004 * playback to headset.
2005 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002006 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002007 out->devices = val;
2008
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302009 if (!out->standby) {
2010 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2011 adev->perf_lock_opts,
2012 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002013 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302014 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2015 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002016
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002017 if (output_drives_call(adev, out)) {
2018 if(!voice_is_in_call(adev)) {
2019 if (adev->mode == AUDIO_MODE_IN_CALL) {
2020 adev->current_call_output = out;
2021 ret = voice_start_call(adev);
2022 }
2023 } else {
2024 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002025 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002026 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002027 }
2028 }
2029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002031 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002033
2034 if (out == adev->primary_output) {
2035 pthread_mutex_lock(&adev->lock);
2036 audio_extn_set_parameters(adev, parms);
2037 pthread_mutex_unlock(&adev->lock);
2038 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002039 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002040 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002041 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002042
2043 audio_extn_dts_create_state_notifier_node(out->usecase);
2044 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2045 popcount(out->channel_mask),
2046 out->playback_started);
2047
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002048 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002049 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302052error:
Eric Laurent994a6932013-07-17 11:51:42 -07002053 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 return ret;
2055}
2056
2057static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2058{
2059 struct stream_out *out = (struct stream_out *)stream;
2060 struct str_parms *query = str_parms_create_str(keys);
2061 char *str;
2062 char value[256];
2063 struct str_parms *reply = str_parms_create();
2064 size_t i, j;
2065 int ret;
2066 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002067
2068 if (!query || !reply) {
2069 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2070 return NULL;
2071 }
2072
Eric Laurent994a6932013-07-17 11:51:42 -07002073 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2075 if (ret >= 0) {
2076 value[0] = '\0';
2077 i = 0;
2078 while (out->supported_channel_masks[i] != 0) {
2079 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2080 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2081 if (!first) {
2082 strcat(value, "|");
2083 }
2084 strcat(value, out_channels_name_to_enum_table[j].name);
2085 first = false;
2086 break;
2087 }
2088 }
2089 i++;
2090 }
2091 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2092 str = str_parms_to_str(reply);
2093 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002094 voice_extn_out_get_parameters(out, query, reply);
2095 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002096 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002097 free(str);
2098 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002101
Alexy Joseph62142aa2015-11-16 15:10:34 -08002102
2103 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2104 if (ret >= 0) {
2105 value[0] = '\0';
2106 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2107 ALOGV("in direct_pcm");
2108 strlcat(value, "true", strlen("true"));
2109 } else {
2110 ALOGV("not in direct_pcm");
2111 strlcat(value, "false", strlen("false"));
2112 }
2113 str_parms_add_str(reply, "is_direct_pcm_track", value);
2114 str = str_parms_to_str(reply);
2115 }
2116
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002117 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2118 if (ret >= 0) {
2119 value[0] = '\0';
2120 i = 0;
2121 first = true;
2122 while (out->supported_formats[i] != 0) {
2123 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2124 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2125 if (!first) {
2126 strcat(value, "|");
2127 }
2128 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2129 first = false;
2130 break;
2131 }
2132 }
2133 i++;
2134 }
2135 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2136 str = str_parms_to_str(reply);
2137 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 str_parms_destroy(query);
2139 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002140 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 return str;
2142}
2143
2144static uint32_t out_get_latency(const struct audio_stream_out *stream)
2145{
2146 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002147 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148
Alexy Josephaa54c872014-12-03 02:46:47 -08002149 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002150 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002151 } else {
2152 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002154 }
2155
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302156 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002157 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158}
2159
2160static int out_set_volume(struct audio_stream_out *stream, float left,
2161 float right)
2162{
Eric Laurenta9024de2013-04-04 09:19:12 -07002163 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 int volume[2];
2165
Eric Laurenta9024de2013-04-04 09:19:12 -07002166 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2167 /* only take left channel into account: the API is for stereo anyway */
2168 out->muted = (left == 0.0f);
2169 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002170 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002171 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2172 /*
2173 * Set mute or umute on HDMI passthrough stream.
2174 * Only take left channel into account.
2175 * Mute is 0 and unmute 1
2176 */
2177 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2178 } else {
2179 char mixer_ctl_name[128];
2180 struct audio_device *adev = out->dev;
2181 struct mixer_ctl *ctl;
2182 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002183 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002184
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002185 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2186 "Compress Playback %d Volume", pcm_device_id);
2187 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2188 if (!ctl) {
2189 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2190 __func__, mixer_ctl_name);
2191 return -EINVAL;
2192 }
2193 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2194 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2195 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2196 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002198 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 return -ENOSYS;
2201}
2202
2203static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2204 size_t bytes)
2205{
2206 struct stream_out *out = (struct stream_out *)stream;
2207 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302208 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002209 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002211 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302212
Naresh Tanniru80659832014-06-04 18:17:56 +05302213 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002214 // increase written size during SSR to avoid mismatch
2215 // with the written frames count in AF
2216 if (!is_offload_usecase(out->usecase))
2217 out->written += bytes / (out->config.channels * sizeof(short));
2218
Naresh Tanniru80659832014-06-04 18:17:56 +05302219 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302220 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302221 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302222 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002223 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302224 //during SSR for compress usecase we should return error to flinger
2225 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2226 pthread_mutex_unlock(&out->lock);
2227 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302228 }
2229 }
2230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002232 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002233 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002234 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2235 ret = voice_extn_compress_voip_start_output_stream(out);
2236 else
2237 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002238 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002241 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 goto exit;
2243 }
vivek mehta446c3962015-09-14 10:57:35 -07002244 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002245 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247
Ashish Jain81eb2a82015-05-13 10:52:34 +05302248 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2249 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2250 adev->is_channel_status_set = true;
2251 }
2252
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002253 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002254 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002255 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002256 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002257 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2258 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302259 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2260 ALOGD("copl(%p):send next track params in gapless", out);
2261 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2262 out->send_next_track_params = false;
2263 out->is_compr_metadata_avail = false;
2264 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002265 }
2266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302268 if (ret < 0)
2269 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002270 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002271 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302272 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002273 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302274 } else if (-ENETRESET == ret) {
2275 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2276 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2277 pthread_mutex_unlock(&out->lock);
2278 out_standby(&out->stream.common);
2279 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302281 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002283 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 out->playback_started = 1;
2285 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002286
2287 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2288 popcount(out->channel_mask),
2289 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002290 }
2291 pthread_mutex_unlock(&out->lock);
2292 return ret;
2293 } else {
2294 if (out->pcm) {
2295 if (out->muted)
2296 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002297
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002299
2300 if (adev->adm_request_focus)
2301 adev->adm_request_focus(adev->adm_data, out->handle);
2302
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002303 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2304 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2305 else
2306 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002307
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302308 if (ret < 0)
2309 ret = -errno;
2310 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002311 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002312
2313 if (adev->adm_abandon_focus)
2314 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 }
2317
2318exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302319 /* ToDo: There may be a corner case when SSR happens back to back during
2320 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302321 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302322 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302323 }
2324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325 pthread_mutex_unlock(&out->lock);
2326
2327 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002328 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002329 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302330 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302331 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302332 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302333 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302334 out->standby = true;
2335 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002337 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302338 out_get_sample_rate(&out->stream.common));
2339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 }
2341 return bytes;
2342}
2343
2344static int out_get_render_position(const struct audio_stream_out *stream,
2345 uint32_t *dsp_frames)
2346{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302348 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002349
2350 if (dsp_frames == NULL)
2351 return -EINVAL;
2352
2353 *dsp_frames = 0;
2354 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002355 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002356 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302358 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302360 if (ret < 0)
2361 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 ALOGVV("%s rendered frames %d sample_rate %d",
2363 __func__, *dsp_frames, out->sample_rate);
2364 }
2365 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302366 if (-ENETRESET == ret) {
2367 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2368 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2369 return -EINVAL;
2370 } else if(ret < 0) {
2371 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2372 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302373 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2374 /*
2375 * Handle corner case where compress session is closed during SSR
2376 * and timestamp is queried
2377 */
2378 ALOGE(" ERROR: sound card not active, return error");
2379 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302380 } else {
2381 return 0;
2382 }
Zhou Song32a556e2015-05-05 10:46:56 +08002383 } else if (audio_is_linear_pcm(out->format)) {
2384 *dsp_frames = out->written;
2385 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 } else
2387 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388}
2389
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002390static int out_add_audio_effect(const struct audio_stream *stream __unused,
2391 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392{
2393 return 0;
2394}
2395
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002396static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2397 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398{
2399 return 0;
2400}
2401
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002402static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2403 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404{
2405 return -EINVAL;
2406}
2407
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002408static int out_get_presentation_position(const struct audio_stream_out *stream,
2409 uint64_t *frames, struct timespec *timestamp)
2410{
2411 struct stream_out *out = (struct stream_out *)stream;
2412 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002413 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002414
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002415 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002416
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002417 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002418 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302419 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002420 &out->sample_rate);
2421 ALOGVV("%s rendered frames %ld sample_rate %d",
2422 __func__, dsp_frames, out->sample_rate);
2423 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302424 if (ret < 0)
2425 ret = -errno;
2426 if (-ENETRESET == ret) {
2427 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2428 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2429 ret = -EINVAL;
2430 } else
2431 ret = 0;
2432
Eric Laurent949a0892013-09-20 09:20:13 -07002433 /* this is the best we can do */
2434 clock_gettime(CLOCK_MONOTONIC, timestamp);
2435 }
2436 } else {
2437 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002438 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002439 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2440 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002441 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002442 // This adjustment accounts for buffering after app processor.
2443 // It is based on estimated DSP latency per use case, rather than exact.
2444 signed_frames -=
2445 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2446
Eric Laurent949a0892013-09-20 09:20:13 -07002447 // It would be unusual for this value to be negative, but check just in case ...
2448 if (signed_frames >= 0) {
2449 *frames = signed_frames;
2450 ret = 0;
2451 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002452 }
2453 }
2454 }
2455
2456 pthread_mutex_unlock(&out->lock);
2457
2458 return ret;
2459}
2460
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461static int out_set_callback(struct audio_stream_out *stream,
2462 stream_callback_t callback, void *cookie)
2463{
2464 struct stream_out *out = (struct stream_out *)stream;
2465
2466 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002467 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 out->offload_callback = callback;
2469 out->offload_cookie = cookie;
2470 pthread_mutex_unlock(&out->lock);
2471 return 0;
2472}
2473
2474static int out_pause(struct audio_stream_out* stream)
2475{
2476 struct stream_out *out = (struct stream_out *)stream;
2477 int status = -ENOSYS;
2478 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002479 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002480 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002481 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302483 struct audio_device *adev = out->dev;
2484 int snd_scard_state = get_snd_card_state(adev);
2485
2486 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2487 status = compress_pause(out->compr);
2488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002489 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002490
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302491 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002492 audio_extn_dts_notify_playback_state(out->usecase, 0,
2493 out->sample_rate, popcount(out->channel_mask),
2494 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002495 }
2496 pthread_mutex_unlock(&out->lock);
2497 }
2498 return status;
2499}
2500
2501static int out_resume(struct audio_stream_out* stream)
2502{
2503 struct stream_out *out = (struct stream_out *)stream;
2504 int status = -ENOSYS;
2505 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002506 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002507 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002509 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002510 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302511 struct audio_device *adev = out->dev;
2512 int snd_scard_state = get_snd_card_state(adev);
2513
2514 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2515 status = compress_resume(out->compr);
2516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002518
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302519 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002520 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2521 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002522 }
2523 pthread_mutex_unlock(&out->lock);
2524 }
2525 return status;
2526}
2527
2528static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2529{
2530 struct stream_out *out = (struct stream_out *)stream;
2531 int status = -ENOSYS;
2532 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002533 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002534 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2536 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2537 else
2538 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2539 pthread_mutex_unlock(&out->lock);
2540 }
2541 return status;
2542}
2543
2544static int out_flush(struct audio_stream_out* stream)
2545{
2546 struct stream_out *out = (struct stream_out *)stream;
2547 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002548 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002549 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002550 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551 stop_compressed_output_l(out);
2552 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002553 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002554 return 0;
2555 }
2556 return -ENOSYS;
2557}
2558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559/** audio_stream_in implementation **/
2560static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2561{
2562 struct stream_in *in = (struct stream_in *)stream;
2563
2564 return in->config.rate;
2565}
2566
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002567static int in_set_sample_rate(struct audio_stream *stream __unused,
2568 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569{
2570 return -ENOSYS;
2571}
2572
2573static size_t in_get_buffer_size(const struct audio_stream *stream)
2574{
2575 struct stream_in *in = (struct stream_in *)stream;
2576
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2578 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002579 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2580 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002581
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002582 return in->config.period_size *
2583 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584}
2585
2586static uint32_t in_get_channels(const struct audio_stream *stream)
2587{
2588 struct stream_in *in = (struct stream_in *)stream;
2589
2590 return in->channel_mask;
2591}
2592
2593static audio_format_t in_get_format(const struct audio_stream *stream)
2594{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002595 struct stream_in *in = (struct stream_in *)stream;
2596
2597 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598}
2599
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002600static int in_set_format(struct audio_stream *stream __unused,
2601 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602{
2603 return -ENOSYS;
2604}
2605
2606static int in_standby(struct audio_stream *stream)
2607{
2608 struct stream_in *in = (struct stream_in *)stream;
2609 struct audio_device *adev = in->dev;
2610 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302611 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2612 stream, in->usecase, use_case_table[in->usecase]);
2613
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002614 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2615 /* Ignore standby in case of voip call because the voip input
2616 * stream is closed in adev_close_input_stream()
2617 */
2618 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2619 return status;
2620 }
2621
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002622 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002623 if (!in->standby && in->is_st_session) {
2624 ALOGD("%s: sound trigger pcm stop lab", __func__);
2625 audio_extn_sound_trigger_stop_lab(in);
2626 in->standby = 1;
2627 }
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002630 if (adev->adm_deregister_stream)
2631 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2632
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002633 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002635 if (in->pcm) {
2636 pcm_close(in->pcm);
2637 in->pcm = NULL;
2638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002640 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 }
2642 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002643 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 return status;
2645}
2646
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002647static int in_dump(const struct audio_stream *stream __unused,
2648 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649{
2650 return 0;
2651}
2652
2653static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2654{
2655 struct stream_in *in = (struct stream_in *)stream;
2656 struct audio_device *adev = in->dev;
2657 struct str_parms *parms;
2658 char *str;
2659 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002660 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302662 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 parms = str_parms_create_str(kvpairs);
2664
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302665 if (!parms)
2666 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002667 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002668 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002669
2670 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2671 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 val = atoi(value);
2673 /* no audio source uses val == 0 */
2674 if ((in->source != val) && (val != 0)) {
2675 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002676 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2677 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2678 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2679 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002680 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002681 err = voice_extn_compress_voip_open_input_stream(in);
2682 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002683 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002684 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002685 }
2686 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 }
2688 }
2689
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002690 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2691 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002693 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 in->device = val;
2695 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002696 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002697 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 }
2699 }
2700
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002701done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002703 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704
2705 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302706error:
Eric Laurent994a6932013-07-17 11:51:42 -07002707 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 return ret;
2709}
2710
2711static char* in_get_parameters(const struct audio_stream *stream,
2712 const char *keys)
2713{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002714 struct stream_in *in = (struct stream_in *)stream;
2715 struct str_parms *query = str_parms_create_str(keys);
2716 char *str;
2717 char value[256];
2718 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002719
2720 if (!query || !reply) {
2721 ALOGE("in_get_parameters: failed to create query or reply");
2722 return NULL;
2723 }
2724
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002725 ALOGV("%s: enter: keys - %s", __func__, keys);
2726
2727 voice_extn_in_get_parameters(in, query, reply);
2728
2729 str = str_parms_to_str(reply);
2730 str_parms_destroy(query);
2731 str_parms_destroy(reply);
2732
2733 ALOGV("%s: exit: returns - %s", __func__, str);
2734 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735}
2736
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002737static int in_set_gain(struct audio_stream_in *stream __unused,
2738 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739{
2740 return 0;
2741}
2742
2743static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2744 size_t bytes)
2745{
2746 struct stream_in *in = (struct stream_in *)stream;
2747 struct audio_device *adev = in->dev;
2748 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302749 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002751 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302752
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002753 if (in->is_st_session) {
2754 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2755 /* Read from sound trigger HAL */
2756 audio_extn_sound_trigger_read(in, buffer, bytes);
2757 pthread_mutex_unlock(&in->lock);
2758 return bytes;
2759 }
2760
2761 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2762 ALOGD(" %s: sound card is not active/SSR state", __func__);
2763 ret= -EIO;;
2764 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302765 }
2766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002768 pthread_mutex_lock(&adev->lock);
2769 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2770 ret = voice_extn_compress_voip_start_input_stream(in);
2771 else
2772 ret = start_input_stream(in);
2773 pthread_mutex_unlock(&adev->lock);
2774 if (ret != 0) {
2775 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 }
2777 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002778 if (adev->adm_register_input_stream)
2779 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002782 if (adev->adm_request_focus)
2783 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002786 if (audio_extn_ssr_get_enabled() &&
2787 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002788 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002789 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2790 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002791 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2792 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002793 else
2794 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302795 if (ret < 0)
2796 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 }
2798
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002799 if (adev->adm_abandon_focus)
2800 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 /*
2803 * Instead of writing zeroes here, we could trust the hardware
2804 * to always provide zeroes when muted.
2805 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302806 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2807 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 memset(buffer, 0, bytes);
2809
2810exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302811 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302812 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002813 if (-ENETRESET == ret)
2814 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 pthread_mutex_unlock(&in->lock);
2817
2818 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302819 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302820 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302821 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302822 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302823 in->standby = true;
2824 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302825 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002827 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002828 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302829 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 }
2831 return bytes;
2832}
2833
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002834static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835{
2836 return 0;
2837}
2838
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002839static int add_remove_audio_effect(const struct audio_stream *stream,
2840 effect_handle_t effect,
2841 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002843 struct stream_in *in = (struct stream_in *)stream;
2844 int status = 0;
2845 effect_descriptor_t desc;
2846
2847 status = (*effect)->get_descriptor(effect, &desc);
2848 if (status != 0)
2849 return status;
2850
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002851 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002852 pthread_mutex_lock(&in->dev->lock);
2853 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2854 in->enable_aec != enable &&
2855 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2856 in->enable_aec = enable;
2857 if (!in->standby)
2858 select_devices(in->dev, in->usecase);
2859 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002860 if (in->enable_ns != enable &&
2861 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2862 in->enable_ns = enable;
2863 if (!in->standby)
2864 select_devices(in->dev, in->usecase);
2865 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002866 pthread_mutex_unlock(&in->dev->lock);
2867 pthread_mutex_unlock(&in->lock);
2868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 return 0;
2870}
2871
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002872static int in_add_audio_effect(const struct audio_stream *stream,
2873 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874{
Eric Laurent994a6932013-07-17 11:51:42 -07002875 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002876 return add_remove_audio_effect(stream, effect, true);
2877}
2878
2879static int in_remove_audio_effect(const struct audio_stream *stream,
2880 effect_handle_t effect)
2881{
Eric Laurent994a6932013-07-17 11:51:42 -07002882 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002883 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884}
2885
2886static int adev_open_output_stream(struct audio_hw_device *dev,
2887 audio_io_handle_t handle,
2888 audio_devices_t devices,
2889 audio_output_flags_t flags,
2890 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002891 struct audio_stream_out **stream_out,
2892 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893{
2894 struct audio_device *adev = (struct audio_device *)dev;
2895 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002896 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002897 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302900
2901 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2902 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002903 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302904 return -EINVAL;
2905 }
2906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2908
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302909 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2910 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2911 devices, flags, &out->stream);
2912
2913
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002914 if (!out) {
2915 return -ENOMEM;
2916 }
2917
Haynes Mathew George204045b2015-02-25 20:32:03 -08002918 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002919 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002920 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 if (devices == AUDIO_DEVICE_NONE)
2923 devices = AUDIO_DEVICE_OUT_SPEAKER;
2924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 out->flags = flags;
2926 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002927 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002928 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 out->sample_rate = config->sample_rate;
2930 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2931 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002932 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002933 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002934 out->non_blocking = 0;
2935 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936
2937 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002938 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2939 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002940 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2941 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2942
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002943 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002944 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2945 ret = read_hdmi_channel_masks(out);
2946
2947 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2948 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002949 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002950 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002951 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002952
2953 if (config->sample_rate == 0)
2954 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2955 if (config->channel_mask == 0)
2956 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2957
2958 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2961 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002963 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002965 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2966 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002967 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002968 ret = voice_extn_compress_voip_open_output_stream(out);
2969 if (ret != 0) {
2970 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2971 __func__, ret);
2972 goto error_open;
2973 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002974 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2975 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2976
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2978 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2979 ALOGE("%s: Unsupported Offload information", __func__);
2980 ret = -EINVAL;
2981 goto error_open;
2982 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002983
2984 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2985 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2986 ALOGV("read and update_pass through formats");
2987 ret = audio_extn_dolby_update_passt_formats(adev, out);
2988 if(ret != 0) {
2989 goto error_open;
2990 }
2991 if(config->offload_info.format == 0)
2992 config->offload_info.format = out->supported_formats[0];
2993 }
2994
Mingming Yin90310102013-11-13 16:57:00 -08002995 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002996 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002997 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 ret = -EINVAL;
2999 goto error_open;
3000 }
3001
3002 out->compr_config.codec = (struct snd_codec *)
3003 calloc(1, sizeof(struct snd_codec));
3004
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003005 if (!out->compr_config.codec) {
3006 ret = -ENOMEM;
3007 goto error_open;
3008 }
3009
vivek mehta0ea887a2015-08-26 14:01:20 -07003010 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003011 out->usecase = get_offload_usecase(adev, true);
3012 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003013 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003014 out->stream.set_callback = out_set_callback;
3015 out->stream.pause = out_pause;
3016 out->stream.resume = out_resume;
3017 out->stream.drain = out_drain;
3018 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003019 out->usecase = get_offload_usecase(adev, false);
3020 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003021 }
vivek mehta446c3962015-09-14 10:57:35 -07003022
3023 if (out->usecase == USECASE_INVALID) {
3024 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3025 ret = -EEXIST;
3026 goto error_open;
3027 }
3028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003029 if (config->offload_info.channel_mask)
3030 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003031 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003032 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003033 config->offload_info.channel_mask = config->channel_mask;
3034 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003035 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 out->sample_rate = config->offload_info.sample_rate;
3037
Mingming Yin3ee55c62014-08-04 14:23:35 -07003038 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003040 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003041 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003042 audio_extn_dolby_get_snd_codec_id(adev, out,
3043 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003044 else
3045 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003047
3048 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3049 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003050 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003051 platform_get_pcm_offload_buffer_size(&config->offload_info);
3052 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3053 out->compr_config.fragment_size =
3054 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003055 } else {
3056 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003057 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3060 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003061 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062 out->compr_config.codec->bit_rate =
3063 config->offload_info.bit_rate;
3064 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003065 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303067 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003068 /*TODO: Do we need to change it for passthrough */
3069 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070
Manish Dewangana6fc5442015-08-24 20:30:31 +05303071 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3073 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3074 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003075 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3076 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003077 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003078 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003079 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3080 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003081
Mingming Yin3ee55c62014-08-04 14:23:35 -07003082 if (out->bit_width == 24) {
3083 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3084 }
3085
Amit Shekhar6f461b12014-08-01 14:52:58 -07003086 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303087 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3090 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003091
Mingming Yin497419f2015-07-01 16:57:32 -07003092 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003093 //this flag is set from framework only if its for PCM formats
3094 //no need to check for PCM format again
3095 out->non_blocking = 0;
3096 out->use_small_bufs = true;
3097 ALOGI("Keep write blocking for small buff: non_blockling %d",
3098 out->non_blocking);
3099 }
3100
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003101 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303102 out->send_next_track_params = false;
3103 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003104 out->offload_state = OFFLOAD_STATE_IDLE;
3105 out->playback_started = 0;
3106
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003107 audio_extn_dts_create_state_notifier_node(out->usecase);
3108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 create_offload_callback_thread(out);
3110 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3111 __func__, config->offload_info.version,
3112 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003113 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003114 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003115 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3116 ret = voice_check_and_set_incall_music_usecase(adev, out);
3117 if (ret != 0) {
3118 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3119 __func__, ret);
3120 goto error_open;
3121 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003122 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3123 if (config->sample_rate == 0)
3124 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3125 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3126 config->sample_rate != 8000) {
3127 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3128 ret = -EINVAL;
3129 goto error_open;
3130 }
3131 out->sample_rate = config->sample_rate;
3132 out->config.rate = config->sample_rate;
3133 if (config->format == AUDIO_FORMAT_DEFAULT)
3134 config->format = AUDIO_FORMAT_PCM_16_BIT;
3135 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3136 config->format = AUDIO_FORMAT_PCM_16_BIT;
3137 ret = -EINVAL;
3138 goto error_open;
3139 }
3140 out->format = config->format;
3141 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3142 out->config = pcm_config_afe_proxy_playback;
3143 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003144 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3145 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3146 out->config = pcm_config_low_latency;
3147 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003148 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003149 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3151 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003153 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3154 format = AUDIO_FORMAT_PCM_16_BIT;
3155 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3156 out->config = pcm_config_deep_buffer;
3157 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003158 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003159 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003160 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003161 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003162 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003163 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 }
3165
Amit Shekhar1d896042014-10-03 13:16:09 -07003166 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3167 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003168 /* TODO remove this hardcoding and check why width is zero*/
3169 if (out->bit_width == 0)
3170 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003171 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3172 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003173 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003174 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003175 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3176 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3177 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003178 if(adev->primary_output == NULL)
3179 adev->primary_output = out;
3180 else {
3181 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003182 ret = -EEXIST;
3183 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003184 }
3185 }
3186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 /* Check if this usecase is already existing */
3188 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003189 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3190 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003193 ret = -EEXIST;
3194 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 }
3196 pthread_mutex_unlock(&adev->lock);
3197
3198 out->stream.common.get_sample_rate = out_get_sample_rate;
3199 out->stream.common.set_sample_rate = out_set_sample_rate;
3200 out->stream.common.get_buffer_size = out_get_buffer_size;
3201 out->stream.common.get_channels = out_get_channels;
3202 out->stream.common.get_format = out_get_format;
3203 out->stream.common.set_format = out_set_format;
3204 out->stream.common.standby = out_standby;
3205 out->stream.common.dump = out_dump;
3206 out->stream.common.set_parameters = out_set_parameters;
3207 out->stream.common.get_parameters = out_get_parameters;
3208 out->stream.common.add_audio_effect = out_add_audio_effect;
3209 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3210 out->stream.get_latency = out_get_latency;
3211 out->stream.set_volume = out_set_volume;
3212 out->stream.write = out_write;
3213 out->stream.get_render_position = out_get_render_position;
3214 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003215 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003218 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003219 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220
3221 config->format = out->stream.common.get_format(&out->stream.common);
3222 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3223 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3224
3225 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303226 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003227 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003228
3229 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3230 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3231 popcount(out->channel_mask), out->playback_started);
3232
Eric Laurent994a6932013-07-17 11:51:42 -07003233 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003235
3236error_open:
3237 free(out);
3238 *stream_out = NULL;
3239 ALOGD("%s: exit: ret %d", __func__, ret);
3240 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241}
3242
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003243static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 struct audio_stream_out *stream)
3245{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246 struct stream_out *out = (struct stream_out *)stream;
3247 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003248 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003249
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303250 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3251
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003252 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303253 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003254 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303255 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003256 if(ret != 0)
3257 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3258 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003259 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003260 out_standby(&stream->common);
3261
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003262 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003263 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003265 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003266 if (out->compr_config.codec != NULL)
3267 free(out->compr_config.codec);
3268 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003269
3270 if (adev->voice_tx_output == out)
3271 adev->voice_tx_output = NULL;
3272
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003273 pthread_cond_destroy(&out->cond);
3274 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003276 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277}
3278
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003279static void close_compress_sessions(struct audio_device *adev)
3280{
Mingming Yin7b762e72015-03-04 13:47:32 -08003281 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303282 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003283 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003284 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303285
3286 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003287 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303288 if (is_offload_usecase(usecase->id)) {
3289 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003290 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3291 out = usecase->stream.out;
3292 pthread_mutex_unlock(&adev->lock);
3293 out_standby(&out->stream.common);
3294 pthread_mutex_lock(&adev->lock);
3295 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303296 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003297 }
3298 pthread_mutex_unlock(&adev->lock);
3299}
3300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3302{
3303 struct audio_device *adev = (struct audio_device *)dev;
3304 struct str_parms *parms;
3305 char *str;
3306 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003307 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003308 int ret;
3309 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003311 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303314 if (!parms)
3315 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003316 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3317 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303318 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303319 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303320 struct listnode *node;
3321 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303322 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303323 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003324 //close compress sessions on OFFLINE status
3325 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303326 } else if (strstr(snd_card_status, "ONLINE")) {
3327 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303328 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003329 //send dts hpx license if enabled
3330 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303331 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303332 }
3333
3334 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003335 status = voice_set_parameters(adev, parms);
3336 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003337 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003339 status = platform_set_parameters(adev->platform, parms);
3340 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003341 goto done;
3342
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003343 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3344 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003345 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3347 adev->bluetooth_nrec = true;
3348 else
3349 adev->bluetooth_nrec = false;
3350 }
3351
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003352 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3353 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3355 adev->screen_off = false;
3356 else
3357 adev->screen_off = true;
3358 }
3359
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003360 ret = str_parms_get_int(parms, "rotation", &val);
3361 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003362 bool reverse_speakers = false;
3363 switch(val) {
3364 // FIXME: note that the code below assumes that the speakers are in the correct placement
3365 // relative to the user when the device is rotated 90deg from its default rotation. This
3366 // assumption is device-specific, not platform-specific like this code.
3367 case 270:
3368 reverse_speakers = true;
3369 break;
3370 case 0:
3371 case 90:
3372 case 180:
3373 break;
3374 default:
3375 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003376 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003377 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003378 if (status == 0) {
3379 if (adev->speaker_lr_swap != reverse_speakers) {
3380 adev->speaker_lr_swap = reverse_speakers;
3381 // only update the selected device if there is active pcm playback
3382 struct audio_usecase *usecase;
3383 struct listnode *node;
3384 list_for_each(node, &adev->usecase_list) {
3385 usecase = node_to_item(node, struct audio_usecase, list);
3386 if (usecase->type == PCM_PLAYBACK) {
3387 select_devices(adev, usecase->id);
3388 break;
3389 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003390 }
3391 }
3392 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003393 }
3394
Mingming Yin514a8bc2014-07-29 15:22:21 -07003395 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3396 if (ret >= 0) {
3397 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3398 adev->bt_wb_speech_enabled = true;
3399 else
3400 adev->bt_wb_speech_enabled = false;
3401 }
3402
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003403 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3404 if (ret >= 0) {
3405 val = atoi(value);
3406 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3407 ALOGV("cache new edid");
3408 platform_cache_edid(adev->platform);
3409 }
3410 }
3411
3412 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3413 if (ret >= 0) {
3414 val = atoi(value);
3415 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3416 ALOGV("invalidate cached edid");
3417 platform_invalidate_edid(adev->platform);
3418 }
3419 }
3420
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003421 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003422
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003423done:
3424 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003425 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303426error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003427 ALOGV("%s: exit with code(%d)", __func__, status);
3428 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429}
3430
3431static char* adev_get_parameters(const struct audio_hw_device *dev,
3432 const char *keys)
3433{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003434 struct audio_device *adev = (struct audio_device *)dev;
3435 struct str_parms *reply = str_parms_create();
3436 struct str_parms *query = str_parms_create_str(keys);
3437 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303438 char value[256] = {0};
3439 int ret = 0;
3440
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003441 if (!query || !reply) {
3442 ALOGE("adev_get_parameters: failed to create query or reply");
3443 return NULL;
3444 }
3445
Naresh Tannirud7205b62014-06-20 02:54:48 +05303446 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3447 sizeof(value));
3448 if (ret >=0) {
3449 int val = 1;
3450 pthread_mutex_lock(&adev->snd_card_status.lock);
3451 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3452 val = 0;
3453 pthread_mutex_unlock(&adev->snd_card_status.lock);
3454 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3455 goto exit;
3456 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003457
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003458 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003459 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003460 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003461 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303462 pthread_mutex_unlock(&adev->lock);
3463
Naresh Tannirud7205b62014-06-20 02:54:48 +05303464exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003465 str = str_parms_to_str(reply);
3466 str_parms_destroy(query);
3467 str_parms_destroy(reply);
3468
3469 ALOGV("%s: exit: returns - %s", __func__, str);
3470 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471}
3472
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003473static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474{
3475 return 0;
3476}
3477
3478static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3479{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003480 int ret;
3481 struct audio_device *adev = (struct audio_device *)dev;
3482 pthread_mutex_lock(&adev->lock);
3483 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003484 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003485 pthread_mutex_unlock(&adev->lock);
3486 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487}
3488
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003489static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3490 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
3492 return -ENOSYS;
3493}
3494
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003495static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3496 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497{
3498 return -ENOSYS;
3499}
3500
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003501static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3502 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503{
3504 return -ENOSYS;
3505}
3506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003507static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3508 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509{
3510 return -ENOSYS;
3511}
3512
3513static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3514{
3515 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517 pthread_mutex_lock(&adev->lock);
3518 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003519 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3522 voice_is_in_call(adev)) {
3523 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003524 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003525 adev->current_call_output = NULL;
3526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 }
3528 pthread_mutex_unlock(&adev->lock);
3529 return 0;
3530}
3531
3532static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3533{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003534 int ret;
3535
3536 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003537 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003538 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3539 pthread_mutex_unlock(&adev->lock);
3540
3541 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542}
3543
3544static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3545{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003546 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 return 0;
3548}
3549
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003550static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551 const struct audio_config *config)
3552{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003553 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003555 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3556 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557}
3558
3559static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003560 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 audio_devices_t devices,
3562 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003563 struct audio_stream_in **stream_in,
3564 audio_input_flags_t flags __unused,
3565 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003566 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567{
3568 struct audio_device *adev = (struct audio_device *)dev;
3569 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003570 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003571 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003572 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 *stream_in = NULL;
3575 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3576 return -EINVAL;
3577
3578 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003579
3580 if (!in) {
3581 ALOGE("failed to allocate input stream");
3582 return -ENOMEM;
3583 }
3584
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303585 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003586 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3587 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003589 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003590 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 in->stream.common.get_sample_rate = in_get_sample_rate;
3593 in->stream.common.set_sample_rate = in_set_sample_rate;
3594 in->stream.common.get_buffer_size = in_get_buffer_size;
3595 in->stream.common.get_channels = in_get_channels;
3596 in->stream.common.get_format = in_get_format;
3597 in->stream.common.set_format = in_set_format;
3598 in->stream.common.standby = in_standby;
3599 in->stream.common.dump = in_dump;
3600 in->stream.common.set_parameters = in_set_parameters;
3601 in->stream.common.get_parameters = in_get_parameters;
3602 in->stream.common.add_audio_effect = in_add_audio_effect;
3603 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3604 in->stream.set_gain = in_set_gain;
3605 in->stream.read = in_read;
3606 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3607
3608 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003609 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 in->standby = 1;
3612 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003613 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003614 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615
3616 /* Update config params with the requested sample rate and channels */
3617 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003618 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3619 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3620 is_low_latency = true;
3621#if LOW_LATENCY_CAPTURE_USE_CASE
3622 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3623#endif
3624 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003627 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003629 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303630 if (adev->mode != AUDIO_MODE_IN_CALL) {
3631 ret = -EINVAL;
3632 goto err_open;
3633 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003634 if (config->sample_rate == 0)
3635 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3636 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3637 config->sample_rate != 8000) {
3638 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3639 ret = -EINVAL;
3640 goto err_open;
3641 }
3642 if (config->format == AUDIO_FORMAT_DEFAULT)
3643 config->format = AUDIO_FORMAT_PCM_16_BIT;
3644 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3645 config->format = AUDIO_FORMAT_PCM_16_BIT;
3646 ret = -EINVAL;
3647 goto err_open;
3648 }
3649
3650 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3651 in->config = pcm_config_afe_proxy_record;
3652 in->config.channels = channel_count;
3653 in->config.rate = config->sample_rate;
3654 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003655 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003656 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003657 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3658 ret = -EINVAL;
3659 goto err_open;
3660 }
3661 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003662 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003663 }
Mingming Yine62d7842013-10-25 16:26:03 -07003664 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003665 audio_extn_compr_cap_format_supported(config->format) &&
3666 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003667 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003668 } else {
3669 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003670 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003671 buffer_size = get_input_buffer_size(config->sample_rate,
3672 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003673 channel_count,
3674 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003675 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003676 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3677 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3678 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3679 (in->config.rate == 8000 || in->config.rate == 16000) &&
3680 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3681 voice_extn_compress_voip_open_input_stream(in);
3682 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003683 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003685 /* This stream could be for sound trigger lab,
3686 get sound trigger pcm if present */
3687 audio_extn_sound_trigger_check_and_get_session(in);
3688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003690 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692
3693err_open:
3694 free(in);
3695 *stream_in = NULL;
3696 return ret;
3697}
3698
3699static void adev_close_input_stream(struct audio_hw_device *dev,
3700 struct audio_stream_in *stream)
3701{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003702 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003703 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003704 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303705
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303706 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003707
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303708 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003709 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303710
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003711 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303712 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003713 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303714 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003715 if (ret != 0)
3716 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3717 __func__, ret);
3718 } else
3719 in_standby(&stream->common);
3720
Mingming Yin7b762e72015-03-04 13:47:32 -08003721 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003722 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003723 audio_extn_ssr_deinit();
3724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725
Mingming Yine62d7842013-10-25 16:26:03 -07003726 if(audio_extn_compr_cap_enabled() &&
3727 audio_extn_compr_cap_format_supported(in->config.format))
3728 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003729
3730 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 return;
3732}
3733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003734static int adev_dump(const audio_hw_device_t *device __unused,
3735 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736{
3737 return 0;
3738}
3739
3740static int adev_close(hw_device_t *device)
3741{
3742 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003743
3744 if (!adev)
3745 return 0;
3746
3747 pthread_mutex_lock(&adev_init_lock);
3748
3749 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003750 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003751 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003752 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003753 audio_route_free(adev->audio_route);
3754 free(adev->snd_dev_ref_cnt);
3755 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003756 if (adev->adm_deinit)
3757 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003758 free(device);
3759 adev = NULL;
3760 }
3761 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 return 0;
3764}
3765
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003766/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3767 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3768 * just that it _might_ work.
3769 */
3770static int period_size_is_plausible_for_low_latency(int period_size)
3771{
3772 switch (period_size) {
3773 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003774 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003775 case 240:
3776 case 320:
3777 case 480:
3778 return 1;
3779 default:
3780 return 0;
3781 }
3782}
3783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784static int adev_open(const hw_module_t *module, const char *name,
3785 hw_device_t **device)
3786{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003787 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003789 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3791
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003792 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003793 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003794 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003795 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003796 ALOGD("%s: returning existing instance of adev", __func__);
3797 ALOGD("%s: exit", __func__);
3798 pthread_mutex_unlock(&adev_init_lock);
3799 return 0;
3800 }
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 adev = calloc(1, sizeof(struct audio_device));
3803
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003804 if (!adev) {
3805 pthread_mutex_unlock(&adev_init_lock);
3806 return -ENOMEM;
3807 }
3808
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003809 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3812 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3813 adev->device.common.module = (struct hw_module_t *)module;
3814 adev->device.common.close = adev_close;
3815
3816 adev->device.init_check = adev_init_check;
3817 adev->device.set_voice_volume = adev_set_voice_volume;
3818 adev->device.set_master_volume = adev_set_master_volume;
3819 adev->device.get_master_volume = adev_get_master_volume;
3820 adev->device.set_master_mute = adev_set_master_mute;
3821 adev->device.get_master_mute = adev_get_master_mute;
3822 adev->device.set_mode = adev_set_mode;
3823 adev->device.set_mic_mute = adev_set_mic_mute;
3824 adev->device.get_mic_mute = adev_get_mic_mute;
3825 adev->device.set_parameters = adev_set_parameters;
3826 adev->device.get_parameters = adev_get_parameters;
3827 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3828 adev->device.open_output_stream = adev_open_output_stream;
3829 adev->device.close_output_stream = adev_close_output_stream;
3830 adev->device.open_input_stream = adev_open_input_stream;
3831 adev->device.close_input_stream = adev_close_input_stream;
3832 adev->device.dump = adev_dump;
3833
3834 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003836 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003837 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003840 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003841 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003842 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003843 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003844 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003845 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003846 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303847 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303848 adev->perf_lock_opts[0] = 0x101;
3849 adev->perf_lock_opts[1] = 0x20E;
3850 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303851
3852 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3853 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003855 adev->platform = platform_init(adev);
3856 if (!adev->platform) {
3857 free(adev->snd_dev_ref_cnt);
3858 free(adev);
3859 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3860 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003861 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003862 return -EINVAL;
3863 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003864
Naresh Tanniru4c630392014-05-12 01:05:52 +05303865 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3866
Eric Laurentc4aef752013-09-12 17:45:53 -07003867 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3868 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3869 if (adev->visualizer_lib == NULL) {
3870 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3871 } else {
3872 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3873 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003874 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003875 "visualizer_hal_start_output");
3876 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003877 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003878 "visualizer_hal_stop_output");
3879 }
3880 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003881 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003882 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003883
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003884 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3885 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3886 if (adev->offload_effects_lib == NULL) {
3887 ALOGE("%s: DLOPEN failed for %s", __func__,
3888 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3889 } else {
3890 ALOGV("%s: DLOPEN successful for %s", __func__,
3891 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3892 adev->offload_effects_start_output =
3893 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3894 "offload_effects_bundle_hal_start_output");
3895 adev->offload_effects_stop_output =
3896 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3897 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003898 adev->offload_effects_set_hpx_state =
3899 (int (*)(bool))dlsym(adev->offload_effects_lib,
3900 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303901 adev->offload_effects_get_parameters =
3902 (void (*)(struct str_parms *, struct str_parms *))
3903 dlsym(adev->offload_effects_lib,
3904 "offload_effects_bundle_get_parameters");
3905 adev->offload_effects_set_parameters =
3906 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3907 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003908 }
3909 }
3910
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003911 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3912 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3913 if (adev->adm_lib == NULL) {
3914 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3915 } else {
3916 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3917 adev->adm_init = (adm_init_t)
3918 dlsym(adev->adm_lib, "adm_init");
3919 adev->adm_deinit = (adm_deinit_t)
3920 dlsym(adev->adm_lib, "adm_deinit");
3921 adev->adm_register_input_stream = (adm_register_input_stream_t)
3922 dlsym(adev->adm_lib, "adm_register_input_stream");
3923 adev->adm_register_output_stream = (adm_register_output_stream_t)
3924 dlsym(adev->adm_lib, "adm_register_output_stream");
3925 adev->adm_deregister_stream = (adm_deregister_stream_t)
3926 dlsym(adev->adm_lib, "adm_deregister_stream");
3927 adev->adm_request_focus = (adm_request_focus_t)
3928 dlsym(adev->adm_lib, "adm_request_focus");
3929 adev->adm_abandon_focus = (adm_abandon_focus_t)
3930 dlsym(adev->adm_lib, "adm_abandon_focus");
3931 }
3932 }
3933
Mingming Yin514a8bc2014-07-29 15:22:21 -07003934 adev->bt_wb_speech_enabled = false;
3935
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003936 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937 *device = &adev->device.common;
3938
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003939 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3940 &adev->streams_output_cfg_list);
3941
Kiran Kandi910e1862013-10-29 13:29:42 -07003942 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003943
3944 char value[PROPERTY_VALUE_MAX];
3945 int trial;
3946 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3947 trial = atoi(value);
3948 if (period_size_is_plausible_for_low_latency(trial)) {
3949 pcm_config_low_latency.period_size = trial;
3950 pcm_config_low_latency.start_threshold = trial / 4;
3951 pcm_config_low_latency.avail_min = trial / 4;
3952 configured_low_latency_capture_period_size = trial;
3953 }
3954 }
3955 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3956 trial = atoi(value);
3957 if (period_size_is_plausible_for_low_latency(trial)) {
3958 configured_low_latency_capture_period_size = trial;
3959 }
3960 }
3961
vivek mehta446c3962015-09-14 10:57:35 -07003962 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003963 pthread_mutex_unlock(&adev_init_lock);
3964
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003965 if (adev->adm_init)
3966 adev->adm_data = adev->adm_init();
3967
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303968 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07003969 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 return 0;
3971}
3972
3973static struct hw_module_methods_t hal_module_methods = {
3974 .open = adev_open,
3975};
3976
3977struct audio_module HAL_MODULE_INFO_SYM = {
3978 .common = {
3979 .tag = HARDWARE_MODULE_TAG,
3980 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3981 .hal_api_version = HARDWARE_HAL_API_VERSION,
3982 .id = AUDIO_HARDWARE_MODULE_ID,
3983 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003984 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985 .methods = &hal_module_methods,
3986 },
3987};