blob: cd5437ffc853a98a3a5c0c999de228b85261000e [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);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
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;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
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
Preetam Singh Ranawat61716b12015-12-14 11:55:24 +0530519 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530520 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800521 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700522 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
524 adev->snd_dev_ref_cnt[snd_device]--;
525 return -EINVAL;
526 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200527 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800528 if (audio_extn_spkr_prot_start_processing(snd_device)) {
529 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200530 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800531 return -EINVAL;
532 }
533 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700534 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700535 /* due to the possibility of calibration overwrite between listen
536 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700537 audio_extn_sound_trigger_update_device_status(snd_device,
538 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530539 audio_extn_listen_update_device_status(snd_device,
540 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700541 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700542 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543 audio_extn_sound_trigger_update_device_status(snd_device,
544 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530545 audio_extn_listen_update_device_status(snd_device,
546 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700547 return -EINVAL;
548 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300549 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700550 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 return 0;
553}
554
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700555int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700556 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700558 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
559
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800560 if (snd_device < SND_DEVICE_MIN ||
561 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800562 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800563 return -EINVAL;
564 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
566 ALOGE("%s: device ref cnt is already 0", __func__);
567 return -EINVAL;
568 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700571
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
573 ALOGE("%s: Invalid sound device returned", __func__);
574 return -EINVAL;
575 }
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700578 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800579 /* exit usb play back thread */
580 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
581 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
582 audio_extn_usb_stop_playback();
583
584 /* exit usb capture thread */
585 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700586 audio_extn_usb_stop_capture();
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530587 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530588 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800589 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700590 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700591 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300592 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700593 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300594 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700595
Ashish Jain81eb2a82015-05-13 10:52:34 +0530596 if (snd_device == SND_DEVICE_OUT_HDMI)
597 adev->is_channel_status_set = false;
598
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200599 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700600 audio_extn_sound_trigger_update_device_status(snd_device,
601 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530602 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800603 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700604 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800606 return 0;
607}
608
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609static void check_usecases_codec_backend(struct audio_device *adev,
610 struct audio_usecase *uc_info,
611 snd_device_t snd_device)
612{
613 struct listnode *node;
614 struct audio_usecase *usecase;
615 bool switch_device[AUDIO_USECASE_MAX];
616 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800617 int backend_idx = DEFAULT_CODEC_BACKEND;
618 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619
620 /*
621 * This function is to make sure that all the usecases that are active on
622 * the hardware codec backend are always routed to any one device that is
623 * handled by the hardware codec.
624 * For example, if low-latency and deep-buffer usecases are currently active
625 * on speaker and out_set_parameters(headset) is received on low-latency
626 * output, then we have to make sure deep-buffer is also switched to headset,
627 * because of the limitation that both the devices cannot be enabled
628 * at the same time as they share the same backend.
629 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700630 /*
631 * This call is to check if we need to force routing for a particular stream
632 * If there is a backend configuration change for the device when a
633 * new stream starts, then ADM needs to be closed and re-opened with the new
634 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800635 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700636 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800637 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
638 snd_device);
639 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800641 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800642 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 for (i = 0; i < AUDIO_USECASE_MAX; i++)
644 switch_device[i] = false;
645
646 list_for_each(node, &adev->usecase_list) {
647 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800648
649 if (usecase == uc_info)
650 continue;
651 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
652 ALOGV("%s: backend_idx: %d,"
653 "usecase_backend_idx: %d, curr device: %s, usecase device:"
654 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530655 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800656
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800657 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700658 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800659 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
660 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530661 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800662 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700663 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700664 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 switch_device[usecase->id] = true;
666 num_uc_to_switch++;
667 }
668 }
669
670 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700671 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530673 /* Make sure the previous devices to be disabled first and then enable the
674 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 list_for_each(node, &adev->usecase_list) {
676 usecase = node_to_item(node, struct audio_usecase, list);
677 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700678 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 }
680 }
681
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
684 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700686 }
687 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 /* Re-route all the usecases on the shared backend other than the
690 specified usecase to new snd devices */
691 list_for_each(node, &adev->usecase_list) {
692 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530693 /* Update the out_snd_device only for the usecases that are enabled here */
694 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
695 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530696 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700697 }
698 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 }
700}
701
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700702static void check_and_route_capture_usecases(struct audio_device *adev,
703 struct audio_usecase *uc_info,
704 snd_device_t snd_device)
705{
706 struct listnode *node;
707 struct audio_usecase *usecase;
708 bool switch_device[AUDIO_USECASE_MAX];
709 int i, num_uc_to_switch = 0;
710
711 /*
712 * This function is to make sure that all the active capture usecases
713 * are always routed to the same input sound device.
714 * For example, if audio-record and voice-call usecases are currently
715 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
716 * is received for voice call then we have to make sure that audio-record
717 * usecase is also switched to earpiece i.e. voice-dmic-ef,
718 * because of the limitation that two devices cannot be enabled
719 * at the same time if they share the same backend.
720 */
721 for (i = 0; i < AUDIO_USECASE_MAX; i++)
722 switch_device[i] = false;
723
724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800726 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700728 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700729 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
730 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700731 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
733 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700734 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 switch_device[usecase->id] = true;
737 num_uc_to_switch++;
738 }
739 }
740
741 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700742 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530744 /* Make sure the previous devices to be disabled first and then enable the
745 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700746 list_for_each(node, &adev->usecase_list) {
747 usecase = node_to_item(node, struct audio_usecase, list);
748 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700749 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800750 }
751 }
752
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700756 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700757 }
758 }
759
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 /* Re-route all the usecases on the shared backend other than the
761 specified usecase to new snd devices */
762 list_for_each(node, &adev->usecase_list) {
763 usecase = node_to_item(node, struct audio_usecase, list);
764 /* Update the in_snd_device only before enabling the audio route */
765 if (switch_device[usecase->id] ) {
766 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800767 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530768 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700769 }
770 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700771 }
772}
773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700775static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700778 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779
780 switch (channels) {
781 /*
782 * Do not handle stereo output in Multi-channel cases
783 * Stereo case is handled in normal playback path
784 */
785 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700786 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 break;
793 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700794 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
799 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800801 break;
802 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700803 ALOGE("HDMI does not support multi channel playback");
804 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805 break;
806 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700807 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808}
809
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800810audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
811 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700812{
813 struct audio_usecase *usecase;
814 struct listnode *node;
815
816 list_for_each(node, &adev->usecase_list) {
817 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800818 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700819 ALOGV("%s: usecase id %d", __func__, usecase->id);
820 return usecase->id;
821 }
822 }
823 return USECASE_INVALID;
824}
825
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700826struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700827 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828{
829 struct audio_usecase *usecase;
830 struct listnode *node;
831
832 list_for_each(node, &adev->usecase_list) {
833 usecase = node_to_item(node, struct audio_usecase, list);
834 if (usecase->id == uc_id)
835 return usecase;
836 }
837 return NULL;
838}
839
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700840int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800842 snd_device_t out_snd_device = SND_DEVICE_NONE;
843 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 struct audio_usecase *usecase = NULL;
845 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800846 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800847 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800848 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800849 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 usecase = get_usecase_from_list(adev, uc_id);
853 if (usecase == NULL) {
854 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
855 return -EINVAL;
856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800858 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800859 (usecase->type == VOIP_CALL) ||
860 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700861 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800862 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700863 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 usecase->devices = usecase->stream.out->devices;
865 } else {
866 /*
867 * If the voice call is active, use the sound devices of voice call usecase
868 * so that it would not result any device switch. All the usecases will
869 * be switched to new device when select_devices() is called for voice call
870 * usecase. This is to avoid switching devices for voice call when
871 * check_usecases_codec_backend() is called below.
872 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700873 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700874 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800875 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
877 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 in_snd_device = vc_usecase->in_snd_device;
879 out_snd_device = vc_usecase->out_snd_device;
880 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800881 } else if (voice_extn_compress_voip_is_active(adev)) {
882 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530884 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700885 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800886 in_snd_device = voip_usecase->in_snd_device;
887 out_snd_device = voip_usecase->out_snd_device;
888 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800889 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800890 hfp_ucid = audio_extn_hfp_get_usecase();
891 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700892 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800893 in_snd_device = hfp_usecase->in_snd_device;
894 out_snd_device = hfp_usecase->out_snd_device;
895 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 }
897 if (usecase->type == PCM_PLAYBACK) {
898 usecase->devices = usecase->stream.out->devices;
899 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800902 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (usecase->stream.out == adev->primary_output &&
904 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800905 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700906 select_devices(adev, adev->active_input->usecase);
907 }
908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 } else if (usecase->type == PCM_CAPTURE) {
910 usecase->devices = usecase->stream.in->device;
911 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700912 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700913 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530914 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
915 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
916 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
917 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700918 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700919 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
921 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700922 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700923 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700924 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 }
926 }
927
928 if (out_snd_device == usecase->out_snd_device &&
929 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800930 return 0;
931 }
932
sangwoobc677242013-08-08 16:53:43 +0900933 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700934 out_snd_device, platform_get_snd_device_name(out_snd_device),
935 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 /*
938 * Limitation: While in call, to do a device switch we need to disable
939 * and enable both RX and TX devices though one of them is same as current
940 * device.
941 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700942 if ((usecase->type == VOICE_CALL) &&
943 (usecase->in_snd_device != SND_DEVICE_NONE) &&
944 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700945 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700946 }
947
948 if (((usecase->type == VOICE_CALL) ||
949 (usecase->type == VOIP_CALL)) &&
950 (usecase->out_snd_device != SND_DEVICE_NONE)) {
951 /* Disable sidetone only if voice/voip call already exists */
952 if (voice_is_call_state_active(adev) ||
953 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700954 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800955 }
956
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700957 /* Disable current sound devices */
958 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700959 disable_audio_route(adev, usecase);
960 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961 }
962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 disable_audio_route(adev, usecase);
965 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 }
967
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800968 /* Applicable only on the targets that has external modem.
969 * New device information should be sent to modem before enabling
970 * the devices to reduce in-call device switch time.
971 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700972 if ((usecase->type == VOICE_CALL) &&
973 (usecase->in_snd_device != SND_DEVICE_NONE) &&
974 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800975 status = platform_switch_voice_call_enable_device_config(adev->platform,
976 out_snd_device,
977 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700978 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800979
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 /* Enable new sound devices */
981 if (out_snd_device != SND_DEVICE_NONE) {
982 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
983 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700984 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 }
986
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 if (in_snd_device != SND_DEVICE_NONE) {
988 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700989 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991
Avinash Vaish71a8b972014-07-24 15:36:33 +0530992 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700993 status = platform_switch_voice_call_device_post(adev->platform,
994 out_snd_device,
995 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530996 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700997 /* Enable sidetone only if voice/voip call already exists */
998 if (voice_is_call_state_active(adev) ||
999 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001000 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301001 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001002
sangwoo170731f2013-06-08 15:36:36 +09001003 usecase->in_snd_device = in_snd_device;
1004 usecase->out_snd_device = out_snd_device;
1005
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301006 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001007 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301008 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001009 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301010 usecase->stream.out->flags,
1011 usecase->stream.out->format,
1012 usecase->stream.out->sample_rate,
1013 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301014 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301015 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001016 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301017 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001018
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001019 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001020
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001021 /* Applicable only on the targets that has external modem.
1022 * Enable device command should be sent to modem only after
1023 * enabling voice call mixer controls
1024 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001025 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001026 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1027 out_snd_device,
1028 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301029 ALOGD("%s: done",__func__);
1030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 return status;
1032}
1033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034static int stop_input_stream(struct stream_in *in)
1035{
1036 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037 struct audio_usecase *uc_info;
1038 struct audio_device *adev = in->dev;
1039
Eric Laurentc8400632013-02-14 19:04:54 -08001040 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041
Eric Laurent994a6932013-07-17 11:51:42 -07001042 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044 uc_info = get_usecase_from_list(adev, in->usecase);
1045 if (uc_info == NULL) {
1046 ALOGE("%s: Could not find the usecase (%d) in the list",
1047 __func__, in->usecase);
1048 return -EINVAL;
1049 }
1050
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001051 /* Close in-call recording streams */
1052 voice_check_and_stop_incall_rec_usecase(adev, in);
1053
Eric Laurent150dbfe2013-02-27 14:31:02 -08001054 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001055 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056
1057 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001058 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001060 list_remove(&uc_info->list);
1061 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062
Eric Laurent994a6932013-07-17 11:51:42 -07001063 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 return ret;
1065}
1066
1067int start_input_stream(struct stream_in *in)
1068{
1069 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001070 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 struct audio_usecase *uc_info;
1072 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301073 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074
Mingming Yin2664a5b2015-09-03 10:53:11 -07001075 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1076 if (get_usecase_from_list(adev, usecase) == NULL)
1077 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301078 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1079 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001080
Naresh Tanniru80659832014-06-04 18:17:56 +05301081
1082 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301083 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301084 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301085 goto error_config;
1086 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001088 /* Check if source matches incall recording usecase criteria */
1089 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1090 if (ret)
1091 goto error_config;
1092 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001093 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1094
1095 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1096 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1097 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1098 goto error_config;
1099 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001100
Eric Laurentb23d5282013-05-14 15:27:20 -07001101 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102 if (in->pcm_device_id < 0) {
1103 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1104 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001105 ret = -EINVAL;
1106 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108
1109 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001111
1112 if (!uc_info) {
1113 ret = -ENOMEM;
1114 goto error_config;
1115 }
1116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 uc_info->id = in->usecase;
1118 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001119 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 uc_info->devices = in->device;
1121 uc_info->in_snd_device = SND_DEVICE_NONE;
1122 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001124 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301125 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1126 adev->perf_lock_opts,
1127 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129
Eric Laurentc8400632013-02-14 19:04:54 -08001130 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001131 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1132
1133 unsigned int flags = PCM_IN;
1134 unsigned int pcm_open_retry_count = 0;
1135
1136 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1137 flags |= PCM_MMAP | PCM_NOIRQ;
1138 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1139 }
1140
1141 while (1) {
1142 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1143 flags, &in->config);
1144 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1145 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1146 if (in->pcm != NULL) {
1147 pcm_close(in->pcm);
1148 in->pcm = NULL;
1149 }
1150 if (pcm_open_retry_count-- == 0) {
1151 ret = -EIO;
1152 goto error_open;
1153 }
1154 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1155 continue;
1156 }
1157 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001159
1160 ALOGV("%s: pcm_prepare", __func__);
1161 ret = pcm_prepare(in->pcm);
1162 if (ret < 0) {
1163 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1164 pcm_close(in->pcm);
1165 in->pcm = NULL;
1166 goto error_open;
1167 }
1168
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301169 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001170 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001171
Eric Laurentc8400632013-02-14 19:04:54 -08001172 return ret;
1173
1174error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301175 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001177error_config:
1178 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301179 /*
1180 * sleep 50ms to allow sufficient time for kernel
1181 * drivers to recover incases like SSR.
1182 */
1183 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001185
1186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187}
1188
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001189void lock_input_stream(struct stream_in *in)
1190{
1191 pthread_mutex_lock(&in->pre_lock);
1192 pthread_mutex_lock(&in->lock);
1193 pthread_mutex_unlock(&in->pre_lock);
1194}
1195
1196void lock_output_stream(struct stream_out *out)
1197{
1198 pthread_mutex_lock(&out->pre_lock);
1199 pthread_mutex_lock(&out->lock);
1200 pthread_mutex_unlock(&out->pre_lock);
1201}
1202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203/* must be called with out->lock locked */
1204static int send_offload_cmd_l(struct stream_out* out, int command)
1205{
1206 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1207
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001208 if (!cmd) {
1209 ALOGE("failed to allocate mem for command 0x%x", command);
1210 return -ENOMEM;
1211 }
1212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001213 ALOGVV("%s %d", __func__, command);
1214
1215 cmd->cmd = command;
1216 list_add_tail(&out->offload_cmd_list, &cmd->node);
1217 pthread_cond_signal(&out->offload_cond);
1218 return 0;
1219}
1220
1221/* must be called iwth out->lock locked */
1222static void stop_compressed_output_l(struct stream_out *out)
1223{
1224 out->offload_state = OFFLOAD_STATE_IDLE;
1225 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001226 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001227 if (out->compr != NULL) {
1228 compress_stop(out->compr);
1229 while (out->offload_thread_blocked) {
1230 pthread_cond_wait(&out->cond, &out->lock);
1231 }
1232 }
1233}
1234
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001235bool is_offload_usecase(audio_usecase_t uc_id)
1236{
1237 unsigned int i;
1238 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1239 if (uc_id == offload_usecases[i])
1240 return true;
1241 }
1242 return false;
1243}
1244
vivek mehta446c3962015-09-14 10:57:35 -07001245static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001246{
vivek mehta446c3962015-09-14 10:57:35 -07001247 audio_usecase_t ret_uc = USECASE_INVALID;
1248 unsigned int offload_uc_index;
1249 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1250 if (!adev->multi_offload_enable) {
1251 if (is_direct_pcm)
1252 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1253 else
1254 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001255
vivek mehta446c3962015-09-14 10:57:35 -07001256 pthread_mutex_lock(&adev->lock);
1257 if (get_usecase_from_list(adev, ret_uc) != NULL)
1258 ret_uc = USECASE_INVALID;
1259 pthread_mutex_unlock(&adev->lock);
1260
1261 return ret_uc;
1262 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001263
1264 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001265 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1266 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1267 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1268 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001269 break;
1270 }
1271 }
vivek mehta446c3962015-09-14 10:57:35 -07001272
1273 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1274 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001275}
1276
1277static void free_offload_usecase(struct audio_device *adev,
1278 audio_usecase_t uc_id)
1279{
vivek mehta446c3962015-09-14 10:57:35 -07001280 unsigned int offload_uc_index;
1281 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1282
1283 if (!adev->multi_offload_enable)
1284 return;
1285
1286 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1287 if (offload_usecases[offload_uc_index] == uc_id) {
1288 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001289 break;
1290 }
1291 }
1292 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1293}
1294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295static void *offload_thread_loop(void *context)
1296{
1297 struct stream_out *out = (struct stream_out *) context;
1298 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001299 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1302 set_sched_policy(0, SP_FOREGROUND);
1303 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1304
1305 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001306 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 for (;;) {
1308 struct offload_cmd *cmd = NULL;
1309 stream_callback_event_t event;
1310 bool send_callback = false;
1311
1312 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1313 __func__, list_empty(&out->offload_cmd_list),
1314 out->offload_state);
1315 if (list_empty(&out->offload_cmd_list)) {
1316 ALOGV("%s SLEEPING", __func__);
1317 pthread_cond_wait(&out->offload_cond, &out->lock);
1318 ALOGV("%s RUNNING", __func__);
1319 continue;
1320 }
1321
1322 item = list_head(&out->offload_cmd_list);
1323 cmd = node_to_item(item, struct offload_cmd, node);
1324 list_remove(item);
1325
1326 ALOGVV("%s STATE %d CMD %d out->compr %p",
1327 __func__, out->offload_state, cmd->cmd, out->compr);
1328
1329 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1330 free(cmd);
1331 break;
1332 }
1333
1334 if (out->compr == NULL) {
1335 ALOGE("%s: Compress handle is NULL", __func__);
1336 pthread_cond_signal(&out->cond);
1337 continue;
1338 }
1339 out->offload_thread_blocked = true;
1340 pthread_mutex_unlock(&out->lock);
1341 send_callback = false;
1342 switch(cmd->cmd) {
1343 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001344 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001345 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001346 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 send_callback = true;
1348 event = STREAM_CBK_EVENT_WRITE_READY;
1349 break;
1350 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001351 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301352 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001353 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301354 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001355 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301356 if (ret < 0)
1357 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301358 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301359 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001360 compress_drain(out->compr);
1361 else
1362 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301363 if (ret != -ENETRESET) {
1364 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301365 pthread_mutex_lock(&out->lock);
1366 out->send_new_metadata = 1;
1367 out->send_next_track_params = true;
1368 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301369 event = STREAM_CBK_EVENT_DRAIN_READY;
1370 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1371 } else
1372 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001373 break;
1374 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001375 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001376 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001377 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001378 send_callback = true;
1379 event = STREAM_CBK_EVENT_DRAIN_READY;
1380 break;
1381 default:
1382 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1383 break;
1384 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001385 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001386 out->offload_thread_blocked = false;
1387 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001388 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001389 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001390 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001391 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392 free(cmd);
1393 }
1394
1395 pthread_cond_signal(&out->cond);
1396 while (!list_empty(&out->offload_cmd_list)) {
1397 item = list_head(&out->offload_cmd_list);
1398 list_remove(item);
1399 free(node_to_item(item, struct offload_cmd, node));
1400 }
1401 pthread_mutex_unlock(&out->lock);
1402
1403 return NULL;
1404}
1405
1406static int create_offload_callback_thread(struct stream_out *out)
1407{
1408 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1409 list_init(&out->offload_cmd_list);
1410 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1411 offload_thread_loop, out);
1412 return 0;
1413}
1414
1415static int destroy_offload_callback_thread(struct stream_out *out)
1416{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001417 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001418 stop_compressed_output_l(out);
1419 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1420
1421 pthread_mutex_unlock(&out->lock);
1422 pthread_join(out->offload_thread, (void **) NULL);
1423 pthread_cond_destroy(&out->offload_cond);
1424
1425 return 0;
1426}
1427
Eric Laurent07eeafd2013-10-06 12:52:49 -07001428static bool allow_hdmi_channel_config(struct audio_device *adev)
1429{
1430 struct listnode *node;
1431 struct audio_usecase *usecase;
1432 bool ret = true;
1433
1434 list_for_each(node, &adev->usecase_list) {
1435 usecase = node_to_item(node, struct audio_usecase, list);
1436 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1437 /*
1438 * If voice call is already existing, do not proceed further to avoid
1439 * disabling/enabling both RX and TX devices, CSD calls, etc.
1440 * Once the voice call done, the HDMI channels can be configured to
1441 * max channels of remaining use cases.
1442 */
1443 if (usecase->id == USECASE_VOICE_CALL) {
1444 ALOGD("%s: voice call is active, no change in HDMI channels",
1445 __func__);
1446 ret = false;
1447 break;
1448 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1449 ALOGD("%s: multi channel playback is active, "
1450 "no change in HDMI channels", __func__);
1451 ret = false;
1452 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001453 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001454 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001455 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1456 ", no change in HDMI channels", __func__,
1457 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001458 ret = false;
1459 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001460 }
1461 }
1462 }
1463 return ret;
1464}
1465
1466static int check_and_set_hdmi_channels(struct audio_device *adev,
1467 unsigned int channels)
1468{
1469 struct listnode *node;
1470 struct audio_usecase *usecase;
1471
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001472 unsigned int supported_channels = platform_edid_get_max_channels(
1473 adev->platform);
1474 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001475 /* Check if change in HDMI channel config is allowed */
1476 if (!allow_hdmi_channel_config(adev))
1477 return 0;
1478
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001479 if (channels > supported_channels)
1480 channels = supported_channels;
1481
Eric Laurent07eeafd2013-10-06 12:52:49 -07001482 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001483 ALOGD("%s: Requested channels are same as current channels(%d)",
1484 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001485 return 0;
1486 }
1487
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001488 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001489 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001490 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001491 adev->cur_hdmi_channels = channels;
1492
1493 /*
1494 * Deroute all the playback streams routed to HDMI so that
1495 * the back end is deactivated. Note that backend will not
1496 * be deactivated if any one stream is connected to it.
1497 */
1498 list_for_each(node, &adev->usecase_list) {
1499 usecase = node_to_item(node, struct audio_usecase, list);
1500 if (usecase->type == PCM_PLAYBACK &&
1501 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001502 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503 }
1504 }
1505
1506 /*
1507 * Enable all the streams disabled above. Now the HDMI backend
1508 * will be activated with new channel configuration
1509 */
1510 list_for_each(node, &adev->usecase_list) {
1511 usecase = node_to_item(node, struct audio_usecase, list);
1512 if (usecase->type == PCM_PLAYBACK &&
1513 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001514 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001515 }
1516 }
1517
1518 return 0;
1519}
1520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521static int stop_output_stream(struct stream_out *out)
1522{
1523 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 struct audio_usecase *uc_info;
1525 struct audio_device *adev = out->dev;
1526
Eric Laurent994a6932013-07-17 11:51:42 -07001527 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 uc_info = get_usecase_from_list(adev, out->usecase);
1530 if (uc_info == NULL) {
1531 ALOGE("%s: Could not find the usecase (%d) in the list",
1532 __func__, out->usecase);
1533 return -EINVAL;
1534 }
1535
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001536 if (is_offload_usecase(out->usecase) &&
1537 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001538 if (adev->visualizer_stop_output != NULL)
1539 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001540
1541 audio_extn_dts_remove_state_notifier_node(out->usecase);
1542
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001543 if (adev->offload_effects_stop_output != NULL)
1544 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1545 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001546
Eric Laurent150dbfe2013-02-27 14:31:02 -08001547 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001548 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001549
1550 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001551 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001553 list_remove(&uc_info->list);
1554 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001556 if (is_offload_usecase(out->usecase) &&
1557 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1558 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1559 ALOGV("Disable passthrough , reset mixer to pcm");
1560 /* NO_PASSTHROUGH */
1561 out->compr_config.codec->compr_passthr = 0;
1562 audio_extn_dolby_set_hdmi_config(adev, out);
1563 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1564 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 /* Must be called after removing the usecase from list */
1566 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1567 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1568
Eric Laurent994a6932013-07-17 11:51:42 -07001569 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 return ret;
1571}
1572
1573int start_output_stream(struct stream_out *out)
1574{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001576 int sink_channels = 0;
1577 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 struct audio_usecase *uc_info;
1579 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301580 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001582 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1583 ret = -EINVAL;
1584 goto error_config;
1585 }
1586
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301587 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1588 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1589 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301590
Naresh Tanniru80659832014-06-04 18:17:56 +05301591 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301592 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301593 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301594 goto error_config;
1595 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301596
Eric Laurentb23d5282013-05-14 15:27:20 -07001597 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 if (out->pcm_device_id < 0) {
1599 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1600 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001601 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001602 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 }
1604
1605 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001606
1607 if (!uc_info) {
1608 ret = -ENOMEM;
1609 goto error_config;
1610 }
1611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 uc_info->id = out->usecase;
1613 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001614 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001615 uc_info->devices = out->devices;
1616 uc_info->in_snd_device = SND_DEVICE_NONE;
1617 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001618 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001619 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001620 if (is_offload_usecase(out->usecase)) {
1621 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001622 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1623 }
1624 }
Mingming Yin9c041392014-05-01 15:37:31 -07001625 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1626 if (!strncmp("true", prop_value, 4)) {
1627 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001628 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1629 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001630 check_and_set_hdmi_channels(adev, sink_channels);
1631 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001632 if (is_offload_usecase(out->usecase)) {
1633 unsigned int ch_count = out->compr_config.codec->ch_in;
1634 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1635 /* backend channel config for passthrough stream is stereo */
1636 ch_count = 2;
1637 check_and_set_hdmi_channels(adev, ch_count);
1638 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001639 check_and_set_hdmi_channels(adev, out->config.channels);
1640 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001641 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001642 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001643 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301645 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1646 adev->perf_lock_opts,
1647 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 select_devices(adev, out->usecase);
1649
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001650 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1651 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001652 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001653 unsigned int flags = PCM_OUT;
1654 unsigned int pcm_open_retry_count = 0;
1655 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1656 flags |= PCM_MMAP | PCM_NOIRQ;
1657 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1658 } else
1659 flags |= PCM_MONOTONIC;
1660
1661 while (1) {
1662 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1663 flags, &out->config);
1664 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1665 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1666 if (out->pcm != NULL) {
1667 pcm_close(out->pcm);
1668 out->pcm = NULL;
1669 }
1670 if (pcm_open_retry_count-- == 0) {
1671 ret = -EIO;
1672 goto error_open;
1673 }
1674 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1675 continue;
1676 }
1677 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001678 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001679
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001680 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1681 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001682
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001683 ALOGV("%s: pcm_prepare", __func__);
1684 if (pcm_is_ready(out->pcm)) {
1685 ret = pcm_prepare(out->pcm);
1686 if (ret < 0) {
1687 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1688 pcm_close(out->pcm);
1689 out->pcm = NULL;
1690 goto error_open;
1691 }
1692 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001693 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001694 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1695 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001697 out->compr = compress_open(adev->snd_card,
1698 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 COMPRESS_IN, &out->compr_config);
1700 if (out->compr && !is_compress_ready(out->compr)) {
1701 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1702 compress_close(out->compr);
1703 out->compr = NULL;
1704 ret = -EIO;
1705 goto error_open;
1706 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301707 /* compress_open sends params of the track, so reset the flag here */
1708 out->is_compr_metadata_avail = false;
1709
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 if (out->offload_callback)
1711 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001712
Fred Oh3f43e742015-03-04 18:42:34 -08001713 /* Since small bufs uses blocking writes, a write will be blocked
1714 for the default max poll time (20s) in the event of an SSR.
1715 Reduce the poll time to observe and deal with SSR faster.
1716 */
1717 if (out->use_small_bufs) {
1718 compress_set_max_poll_wait(out->compr, 1000);
1719 }
1720
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001721 audio_extn_dts_create_state_notifier_node(out->usecase);
1722 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1723 popcount(out->channel_mask),
1724 out->playback_started);
1725
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001726#ifdef DS1_DOLBY_DDP_ENABLED
1727 if (audio_extn_is_dolby_format(out->format))
1728 audio_extn_dolby_send_ddp_endp_params(adev);
1729#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001730 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1731 if (adev->visualizer_start_output != NULL)
1732 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1733 if (adev->offload_effects_start_output != NULL)
1734 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001735 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301738 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001739 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301743 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001745error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301746 /*
1747 * sleep 50ms to allow sufficient time for kernel
1748 * drivers to recover incases like SSR.
1749 */
1750 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001751 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752}
1753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754static int check_input_parameters(uint32_t sample_rate,
1755 audio_format_t format,
1756 int channel_count)
1757{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001758 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001760 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001761 !voice_extn_compress_voip_is_format_supported(format) &&
1762 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001763
1764 switch (channel_count) {
1765 case 1:
1766 case 2:
1767 case 6:
1768 break;
1769 default:
1770 ret = -EINVAL;
1771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
1773 switch (sample_rate) {
1774 case 8000:
1775 case 11025:
1776 case 12000:
1777 case 16000:
1778 case 22050:
1779 case 24000:
1780 case 32000:
1781 case 44100:
1782 case 48000:
1783 break;
1784 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001785 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 }
1787
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001788 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789}
1790
1791static size_t get_input_buffer_size(uint32_t sample_rate,
1792 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001793 int channel_count,
1794 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795{
1796 size_t size = 0;
1797
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001798 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1799 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001801 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001802 if (is_low_latency)
1803 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001804 /* ToDo: should use frame_size computed based on the format and
1805 channel_count here. */
1806 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001808 /* make sure the size is multiple of 32 bytes
1809 * At 48 kHz mono 16-bit PCM:
1810 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1811 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1812 */
1813 size += 0x1f;
1814 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001815
1816 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817}
1818
1819static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1820{
1821 struct stream_out *out = (struct stream_out *)stream;
1822
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001823 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824}
1825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001826static int out_set_sample_rate(struct audio_stream *stream __unused,
1827 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828{
1829 return -ENOSYS;
1830}
1831
1832static size_t out_get_buffer_size(const struct audio_stream *stream)
1833{
1834 struct stream_out *out = (struct stream_out *)stream;
1835
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001836 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001838 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1839 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001840
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001841 return out->config.period_size *
1842 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843}
1844
1845static uint32_t out_get_channels(const struct audio_stream *stream)
1846{
1847 struct stream_out *out = (struct stream_out *)stream;
1848
1849 return out->channel_mask;
1850}
1851
1852static audio_format_t out_get_format(const struct audio_stream *stream)
1853{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001854 struct stream_out *out = (struct stream_out *)stream;
1855
1856 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857}
1858
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001859static int out_set_format(struct audio_stream *stream __unused,
1860 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861{
1862 return -ENOSYS;
1863}
1864
1865static int out_standby(struct audio_stream *stream)
1866{
1867 struct stream_out *out = (struct stream_out *)stream;
1868 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301870 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1871 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001872 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1873 /* Ignore standby in case of voip call because the voip output
1874 * stream is closed in adev_close_output_stream()
1875 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301876 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001877 return 0;
1878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001880 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001882 if (adev->adm_deregister_stream)
1883 adev->adm_deregister_stream(adev->adm_data, out->handle);
1884
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001885 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001887 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888 if (out->pcm) {
1889 pcm_close(out->pcm);
1890 out->pcm = NULL;
1891 }
1892 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001893 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001894 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301895 out->send_next_track_params = false;
1896 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001897 out->gapless_mdata.encoder_delay = 0;
1898 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001899 if (out->compr != NULL) {
1900 compress_close(out->compr);
1901 out->compr = NULL;
1902 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001903 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001905 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
1907 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001908 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909 return 0;
1910}
1911
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001912static int out_dump(const struct audio_stream *stream __unused,
1913 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914{
1915 return 0;
1916}
1917
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001918static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1919{
1920 int ret = 0;
1921 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001922
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001923 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001924 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001925 return -EINVAL;
1926 }
1927
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301928 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001929
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001930 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1931 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301932 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001933 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1935 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301936 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001937 }
1938
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001939 ALOGV("%s new encoder delay %u and padding %u", __func__,
1940 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1941
1942 return 0;
1943}
1944
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001945static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1946{
1947 return out == adev->primary_output || out == adev->voice_tx_output;
1948}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1951{
1952 struct stream_out *out = (struct stream_out *)stream;
1953 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001954 struct audio_usecase *usecase;
1955 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 struct str_parms *parms;
1957 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001958 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001959 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960
sangwoobc677242013-08-08 16:53:43 +09001961 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001962 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301964 if (!parms)
1965 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001966 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1967 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001969 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001970 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001972 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301973 * When HDMI cable is unplugged/usb hs is disconnected the
1974 * music playback is paused and the policy manager sends routing=0
1975 * But the audioflingercontinues to write data until standby time
1976 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001977 * Avoid this by routing audio to speaker until standby.
1978 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301979 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1980 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001982 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1983 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001984 }
1985
1986 /*
1987 * select_devices() call below switches all the usecases on the same
1988 * backend to the new device. Refer to check_usecases_codec_backend() in
1989 * the select_devices(). But how do we undo this?
1990 *
1991 * For example, music playback is active on headset (deep-buffer usecase)
1992 * and if we go to ringtones and select a ringtone, low-latency usecase
1993 * will be started on headset+speaker. As we can't enable headset+speaker
1994 * and headset devices at the same time, select_devices() switches the music
1995 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1996 * So when the ringtone playback is completed, how do we undo the same?
1997 *
1998 * We are relying on the out_set_parameters() call on deep-buffer output,
1999 * once the ringtone playback is ended.
2000 * NOTE: We should not check if the current devices are same as new devices.
2001 * Because select_devices() must be called to switch back the music
2002 * playback to headset.
2003 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002004 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002005 out->devices = val;
2006
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302007 if (!out->standby) {
2008 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2009 adev->perf_lock_opts,
2010 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002011 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302012 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2013 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002014
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002015 if (output_drives_call(adev, out)) {
2016 if(!voice_is_in_call(adev)) {
2017 if (adev->mode == AUDIO_MODE_IN_CALL) {
2018 adev->current_call_output = out;
2019 ret = voice_start_call(adev);
2020 }
2021 } else {
2022 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002023 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002024 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002025 }
2026 }
2027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002029 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002031
2032 if (out == adev->primary_output) {
2033 pthread_mutex_lock(&adev->lock);
2034 audio_extn_set_parameters(adev, parms);
2035 pthread_mutex_unlock(&adev->lock);
2036 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002037 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002038 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002039 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002040
2041 audio_extn_dts_create_state_notifier_node(out->usecase);
2042 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2043 popcount(out->channel_mask),
2044 out->playback_started);
2045
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002046 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002047 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302050error:
Eric Laurent994a6932013-07-17 11:51:42 -07002051 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 return ret;
2053}
2054
2055static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2056{
2057 struct stream_out *out = (struct stream_out *)stream;
2058 struct str_parms *query = str_parms_create_str(keys);
2059 char *str;
2060 char value[256];
2061 struct str_parms *reply = str_parms_create();
2062 size_t i, j;
2063 int ret;
2064 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002065
2066 if (!query || !reply) {
2067 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2068 return NULL;
2069 }
2070
Eric Laurent994a6932013-07-17 11:51:42 -07002071 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2073 if (ret >= 0) {
2074 value[0] = '\0';
2075 i = 0;
2076 while (out->supported_channel_masks[i] != 0) {
2077 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2078 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2079 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002080 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002082 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083 first = false;
2084 break;
2085 }
2086 }
2087 i++;
2088 }
2089 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2090 str = str_parms_to_str(reply);
2091 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002092 voice_extn_out_get_parameters(out, query, reply);
2093 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002094 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002095 free(str);
2096 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002097 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002099
Alexy Joseph62142aa2015-11-16 15:10:34 -08002100
2101 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2102 if (ret >= 0) {
2103 value[0] = '\0';
2104 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2105 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302106 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002107 } else {
2108 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302109 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002110 }
2111 str_parms_add_str(reply, "is_direct_pcm_track", value);
2112 str = str_parms_to_str(reply);
2113 }
2114
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002115 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2116 if (ret >= 0) {
2117 value[0] = '\0';
2118 i = 0;
2119 first = true;
2120 while (out->supported_formats[i] != 0) {
2121 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2122 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2123 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002124 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002125 }
2126 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2127 first = false;
2128 break;
2129 }
2130 }
2131 i++;
2132 }
2133 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2134 str = str_parms_to_str(reply);
2135 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 str_parms_destroy(query);
2137 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002138 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 return str;
2140}
2141
2142static uint32_t out_get_latency(const struct audio_stream_out *stream)
2143{
2144 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002145 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146
Alexy Josephaa54c872014-12-03 02:46:47 -08002147 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002148 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002149 } else {
2150 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002152 }
2153
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302154 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002155 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156}
2157
2158static int out_set_volume(struct audio_stream_out *stream, float left,
2159 float right)
2160{
Eric Laurenta9024de2013-04-04 09:19:12 -07002161 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 int volume[2];
2163
Eric Laurenta9024de2013-04-04 09:19:12 -07002164 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2165 /* only take left channel into account: the API is for stereo anyway */
2166 out->muted = (left == 0.0f);
2167 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002168 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002169 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2170 /*
2171 * Set mute or umute on HDMI passthrough stream.
2172 * Only take left channel into account.
2173 * Mute is 0 and unmute 1
2174 */
2175 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2176 } else {
2177 char mixer_ctl_name[128];
2178 struct audio_device *adev = out->dev;
2179 struct mixer_ctl *ctl;
2180 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002181 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002183 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2184 "Compress Playback %d Volume", pcm_device_id);
2185 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2186 if (!ctl) {
2187 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2188 __func__, mixer_ctl_name);
2189 return -EINVAL;
2190 }
2191 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2192 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2193 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2194 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002196 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 return -ENOSYS;
2199}
2200
2201static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2202 size_t bytes)
2203{
2204 struct stream_out *out = (struct stream_out *)stream;
2205 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302206 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002207 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002209 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302210
Naresh Tanniru80659832014-06-04 18:17:56 +05302211 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002212 // increase written size during SSR to avoid mismatch
2213 // with the written frames count in AF
2214 if (!is_offload_usecase(out->usecase))
2215 out->written += bytes / (out->config.channels * sizeof(short));
2216
Naresh Tanniru80659832014-06-04 18:17:56 +05302217 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302218 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302219 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302220 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002221 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 //during SSR for compress usecase we should return error to flinger
2223 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2224 pthread_mutex_unlock(&out->lock);
2225 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302226 }
2227 }
2228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002230 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002231 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002232 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2233 ret = voice_extn_compress_voip_start_output_stream(out);
2234 else
2235 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002236 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002239 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 goto exit;
2241 }
vivek mehta446c3962015-09-14 10:57:35 -07002242 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002243 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Ashish Jain81eb2a82015-05-13 10:52:34 +05302246 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2247 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2248 adev->is_channel_status_set = true;
2249 }
2250
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002251 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002252 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002253 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002254 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002255 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2256 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302257 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2258 ALOGD("copl(%p):send next track params in gapless", out);
2259 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2260 out->send_next_track_params = false;
2261 out->is_compr_metadata_avail = false;
2262 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002263 }
2264
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302266 if (ret < 0)
2267 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002268 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002269 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302270 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302272 } else if (-ENETRESET == ret) {
2273 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2274 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2275 pthread_mutex_unlock(&out->lock);
2276 out_standby(&out->stream.common);
2277 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302279 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002281 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 out->playback_started = 1;
2283 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002284
2285 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2286 popcount(out->channel_mask),
2287 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 }
2289 pthread_mutex_unlock(&out->lock);
2290 return ret;
2291 } else {
2292 if (out->pcm) {
2293 if (out->muted)
2294 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002295
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002297
2298 if (adev->adm_request_focus)
2299 adev->adm_request_focus(adev->adm_data, out->handle);
2300
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002301 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2302 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2303 else
2304 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002305
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302306 if (ret < 0)
2307 ret = -errno;
2308 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002309 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002310
2311 if (adev->adm_abandon_focus)
2312 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
2315
2316exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302317 /* ToDo: There may be a corner case when SSR happens back to back during
2318 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302319 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302320 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302321 }
2322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323 pthread_mutex_unlock(&out->lock);
2324
2325 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002326 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002327 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302328 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302329 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302330 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302331 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302332 out->standby = true;
2333 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002335 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302336 out_get_sample_rate(&out->stream.common));
2337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 }
2339 return bytes;
2340}
2341
2342static int out_get_render_position(const struct audio_stream_out *stream,
2343 uint32_t *dsp_frames)
2344{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302346 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002347
2348 if (dsp_frames == NULL)
2349 return -EINVAL;
2350
2351 *dsp_frames = 0;
2352 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002353 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002354 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302356 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302358 if (ret < 0)
2359 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 ALOGVV("%s rendered frames %d sample_rate %d",
2361 __func__, *dsp_frames, out->sample_rate);
2362 }
2363 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302364 if (-ENETRESET == ret) {
2365 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2366 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2367 return -EINVAL;
2368 } else if(ret < 0) {
2369 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2370 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302371 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2372 /*
2373 * Handle corner case where compress session is closed during SSR
2374 * and timestamp is queried
2375 */
2376 ALOGE(" ERROR: sound card not active, return error");
2377 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302378 } else {
2379 return 0;
2380 }
Zhou Song32a556e2015-05-05 10:46:56 +08002381 } else if (audio_is_linear_pcm(out->format)) {
2382 *dsp_frames = out->written;
2383 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 } else
2385 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386}
2387
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002388static int out_add_audio_effect(const struct audio_stream *stream __unused,
2389 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390{
2391 return 0;
2392}
2393
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002394static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2395 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396{
2397 return 0;
2398}
2399
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002400static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2401 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402{
2403 return -EINVAL;
2404}
2405
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002406static int out_get_presentation_position(const struct audio_stream_out *stream,
2407 uint64_t *frames, struct timespec *timestamp)
2408{
2409 struct stream_out *out = (struct stream_out *)stream;
2410 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002411 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002412
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002413 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002414
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002415 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002416 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302417 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002418 &out->sample_rate);
2419 ALOGVV("%s rendered frames %ld sample_rate %d",
2420 __func__, dsp_frames, out->sample_rate);
2421 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302422 if (ret < 0)
2423 ret = -errno;
2424 if (-ENETRESET == ret) {
2425 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2426 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2427 ret = -EINVAL;
2428 } else
2429 ret = 0;
2430
Eric Laurent949a0892013-09-20 09:20:13 -07002431 /* this is the best we can do */
2432 clock_gettime(CLOCK_MONOTONIC, timestamp);
2433 }
2434 } else {
2435 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002436 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002437 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2438 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002439 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002440 // This adjustment accounts for buffering after app processor.
2441 // It is based on estimated DSP latency per use case, rather than exact.
2442 signed_frames -=
2443 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2444
Eric Laurent949a0892013-09-20 09:20:13 -07002445 // It would be unusual for this value to be negative, but check just in case ...
2446 if (signed_frames >= 0) {
2447 *frames = signed_frames;
2448 ret = 0;
2449 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002450 }
2451 }
2452 }
2453
2454 pthread_mutex_unlock(&out->lock);
2455
2456 return ret;
2457}
2458
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459static int out_set_callback(struct audio_stream_out *stream,
2460 stream_callback_t callback, void *cookie)
2461{
2462 struct stream_out *out = (struct stream_out *)stream;
2463
2464 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 out->offload_callback = callback;
2467 out->offload_cookie = cookie;
2468 pthread_mutex_unlock(&out->lock);
2469 return 0;
2470}
2471
2472static int out_pause(struct audio_stream_out* stream)
2473{
2474 struct stream_out *out = (struct stream_out *)stream;
2475 int status = -ENOSYS;
2476 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002477 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002478 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002479 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302481 struct audio_device *adev = out->dev;
2482 int snd_scard_state = get_snd_card_state(adev);
2483
2484 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2485 status = compress_pause(out->compr);
2486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002488
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302489 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002490 audio_extn_dts_notify_playback_state(out->usecase, 0,
2491 out->sample_rate, popcount(out->channel_mask),
2492 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493 }
2494 pthread_mutex_unlock(&out->lock);
2495 }
2496 return status;
2497}
2498
2499static int out_resume(struct audio_stream_out* stream)
2500{
2501 struct stream_out *out = (struct stream_out *)stream;
2502 int status = -ENOSYS;
2503 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002504 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002505 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002507 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302509 struct audio_device *adev = out->dev;
2510 int snd_scard_state = get_snd_card_state(adev);
2511
2512 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2513 status = compress_resume(out->compr);
2514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002516
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302517 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002518 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2519 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002520 }
2521 pthread_mutex_unlock(&out->lock);
2522 }
2523 return status;
2524}
2525
2526static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2527{
2528 struct stream_out *out = (struct stream_out *)stream;
2529 int status = -ENOSYS;
2530 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002531 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002532 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2534 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2535 else
2536 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2537 pthread_mutex_unlock(&out->lock);
2538 }
2539 return status;
2540}
2541
2542static int out_flush(struct audio_stream_out* stream)
2543{
2544 struct stream_out *out = (struct stream_out *)stream;
2545 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002546 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002547 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002548 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002549 stop_compressed_output_l(out);
2550 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002551 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 return 0;
2553 }
2554 return -ENOSYS;
2555}
2556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557/** audio_stream_in implementation **/
2558static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2559{
2560 struct stream_in *in = (struct stream_in *)stream;
2561
2562 return in->config.rate;
2563}
2564
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002565static int in_set_sample_rate(struct audio_stream *stream __unused,
2566 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567{
2568 return -ENOSYS;
2569}
2570
2571static size_t in_get_buffer_size(const struct audio_stream *stream)
2572{
2573 struct stream_in *in = (struct stream_in *)stream;
2574
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002575 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2576 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002577 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2578 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002579
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002580 return in->config.period_size *
2581 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582}
2583
2584static uint32_t in_get_channels(const struct audio_stream *stream)
2585{
2586 struct stream_in *in = (struct stream_in *)stream;
2587
2588 return in->channel_mask;
2589}
2590
2591static audio_format_t in_get_format(const struct audio_stream *stream)
2592{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 struct stream_in *in = (struct stream_in *)stream;
2594
2595 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596}
2597
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002598static int in_set_format(struct audio_stream *stream __unused,
2599 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600{
2601 return -ENOSYS;
2602}
2603
2604static int in_standby(struct audio_stream *stream)
2605{
2606 struct stream_in *in = (struct stream_in *)stream;
2607 struct audio_device *adev = in->dev;
2608 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302609 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2610 stream, in->usecase, use_case_table[in->usecase]);
2611
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002612 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2613 /* Ignore standby in case of voip call because the voip input
2614 * stream is closed in adev_close_input_stream()
2615 */
2616 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2617 return status;
2618 }
2619
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002620 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002621 if (!in->standby && in->is_st_session) {
2622 ALOGD("%s: sound trigger pcm stop lab", __func__);
2623 audio_extn_sound_trigger_stop_lab(in);
2624 in->standby = 1;
2625 }
2626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002628 if (adev->adm_deregister_stream)
2629 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2630
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002631 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002633 if (in->pcm) {
2634 pcm_close(in->pcm);
2635 in->pcm = NULL;
2636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002638 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 }
2640 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002641 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 return status;
2643}
2644
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002645static int in_dump(const struct audio_stream *stream __unused,
2646 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647{
2648 return 0;
2649}
2650
2651static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2652{
2653 struct stream_in *in = (struct stream_in *)stream;
2654 struct audio_device *adev = in->dev;
2655 struct str_parms *parms;
2656 char *str;
2657 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002658 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302660 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 parms = str_parms_create_str(kvpairs);
2662
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302663 if (!parms)
2664 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002665 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002666 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002667
2668 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2669 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 val = atoi(value);
2671 /* no audio source uses val == 0 */
2672 if ((in->source != val) && (val != 0)) {
2673 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002674 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2675 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2676 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2677 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002678 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002679 err = voice_extn_compress_voip_open_input_stream(in);
2680 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002681 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002682 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002683 }
2684 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
2686 }
2687
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002688 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2689 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002691 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 in->device = val;
2693 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002694 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002695 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 }
2697 }
2698
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002699done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002701 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702
2703 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302704error:
Eric Laurent994a6932013-07-17 11:51:42 -07002705 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 return ret;
2707}
2708
2709static char* in_get_parameters(const struct audio_stream *stream,
2710 const char *keys)
2711{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002712 struct stream_in *in = (struct stream_in *)stream;
2713 struct str_parms *query = str_parms_create_str(keys);
2714 char *str;
2715 char value[256];
2716 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002717
2718 if (!query || !reply) {
2719 ALOGE("in_get_parameters: failed to create query or reply");
2720 return NULL;
2721 }
2722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002723 ALOGV("%s: enter: keys - %s", __func__, keys);
2724
2725 voice_extn_in_get_parameters(in, query, reply);
2726
2727 str = str_parms_to_str(reply);
2728 str_parms_destroy(query);
2729 str_parms_destroy(reply);
2730
2731 ALOGV("%s: exit: returns - %s", __func__, str);
2732 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733}
2734
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002735static int in_set_gain(struct audio_stream_in *stream __unused,
2736 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737{
2738 return 0;
2739}
2740
2741static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2742 size_t bytes)
2743{
2744 struct stream_in *in = (struct stream_in *)stream;
2745 struct audio_device *adev = in->dev;
2746 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302747 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002749 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302750
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002751 if (in->is_st_session) {
2752 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2753 /* Read from sound trigger HAL */
2754 audio_extn_sound_trigger_read(in, buffer, bytes);
2755 pthread_mutex_unlock(&in->lock);
2756 return bytes;
2757 }
2758
2759 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2760 ALOGD(" %s: sound card is not active/SSR state", __func__);
2761 ret= -EIO;;
2762 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302763 }
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002766 pthread_mutex_lock(&adev->lock);
2767 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2768 ret = voice_extn_compress_voip_start_input_stream(in);
2769 else
2770 ret = start_input_stream(in);
2771 pthread_mutex_unlock(&adev->lock);
2772 if (ret != 0) {
2773 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 }
2775 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002776 if (adev->adm_register_input_stream)
2777 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002780 if (adev->adm_request_focus)
2781 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002784 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002785 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002786 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2787 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002788 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2789 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002790 else
2791 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302792 if (ret < 0)
2793 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 }
2795
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002796 if (adev->adm_abandon_focus)
2797 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 /*
2800 * Instead of writing zeroes here, we could trust the hardware
2801 * to always provide zeroes when muted.
2802 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302803 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2804 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 memset(buffer, 0, bytes);
2806
2807exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302808 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302809 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002810 if (-ENETRESET == ret)
2811 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 pthread_mutex_unlock(&in->lock);
2814
2815 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302816 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302817 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302818 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302819 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302820 in->standby = true;
2821 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302822 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002824 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002825 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302826 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 }
2828 return bytes;
2829}
2830
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002831static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832{
2833 return 0;
2834}
2835
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002836static int add_remove_audio_effect(const struct audio_stream *stream,
2837 effect_handle_t effect,
2838 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002840 struct stream_in *in = (struct stream_in *)stream;
2841 int status = 0;
2842 effect_descriptor_t desc;
2843
2844 status = (*effect)->get_descriptor(effect, &desc);
2845 if (status != 0)
2846 return status;
2847
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002848 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002849 pthread_mutex_lock(&in->dev->lock);
2850 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2851 in->enable_aec != enable &&
2852 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2853 in->enable_aec = enable;
2854 if (!in->standby)
2855 select_devices(in->dev, in->usecase);
2856 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002857 if (in->enable_ns != enable &&
2858 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2859 in->enable_ns = enable;
2860 if (!in->standby)
2861 select_devices(in->dev, in->usecase);
2862 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002863 pthread_mutex_unlock(&in->dev->lock);
2864 pthread_mutex_unlock(&in->lock);
2865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866 return 0;
2867}
2868
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002869static int in_add_audio_effect(const struct audio_stream *stream,
2870 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871{
Eric Laurent994a6932013-07-17 11:51:42 -07002872 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002873 return add_remove_audio_effect(stream, effect, true);
2874}
2875
2876static int in_remove_audio_effect(const struct audio_stream *stream,
2877 effect_handle_t effect)
2878{
Eric Laurent994a6932013-07-17 11:51:42 -07002879 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002880 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881}
2882
2883static int adev_open_output_stream(struct audio_hw_device *dev,
2884 audio_io_handle_t handle,
2885 audio_devices_t devices,
2886 audio_output_flags_t flags,
2887 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002888 struct audio_stream_out **stream_out,
2889 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890{
2891 struct audio_device *adev = (struct audio_device *)dev;
2892 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002893 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002894 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302897
2898 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2899 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002900 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302901 return -EINVAL;
2902 }
2903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2905
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302906 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2907 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2908 devices, flags, &out->stream);
2909
2910
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002911 if (!out) {
2912 return -ENOMEM;
2913 }
2914
Haynes Mathew George204045b2015-02-25 20:32:03 -08002915 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002916 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002917 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 if (devices == AUDIO_DEVICE_NONE)
2920 devices = AUDIO_DEVICE_OUT_SPEAKER;
2921
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002922 out->flags = flags;
2923 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002924 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002925 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002926 out->sample_rate = config->sample_rate;
2927 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2928 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002929 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002930 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002931 out->non_blocking = 0;
2932 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933
2934 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002935 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2936 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002937 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2938 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2939
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002940 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002941 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2942 ret = read_hdmi_channel_masks(out);
2943
2944 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2945 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002946 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002947 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002948 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002949
2950 if (config->sample_rate == 0)
2951 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2952 if (config->channel_mask == 0)
2953 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2954
2955 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2958 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002959 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002960 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002962 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2963 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002964 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002965 ret = voice_extn_compress_voip_open_output_stream(out);
2966 if (ret != 0) {
2967 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2968 __func__, ret);
2969 goto error_open;
2970 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002971 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2972 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2973
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002974 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2975 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2976 ALOGE("%s: Unsupported Offload information", __func__);
2977 ret = -EINVAL;
2978 goto error_open;
2979 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002980
2981 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2982 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2983 ALOGV("read and update_pass through formats");
2984 ret = audio_extn_dolby_update_passt_formats(adev, out);
2985 if(ret != 0) {
2986 goto error_open;
2987 }
2988 if(config->offload_info.format == 0)
2989 config->offload_info.format = out->supported_formats[0];
2990 }
2991
Mingming Yin90310102013-11-13 16:57:00 -08002992 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002993 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002994 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002995 ret = -EINVAL;
2996 goto error_open;
2997 }
2998
2999 out->compr_config.codec = (struct snd_codec *)
3000 calloc(1, sizeof(struct snd_codec));
3001
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003002 if (!out->compr_config.codec) {
3003 ret = -ENOMEM;
3004 goto error_open;
3005 }
3006
vivek mehta0ea887a2015-08-26 14:01:20 -07003007 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003008 out->usecase = get_offload_usecase(adev, true);
3009 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003010 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003011 out->stream.set_callback = out_set_callback;
3012 out->stream.pause = out_pause;
3013 out->stream.resume = out_resume;
3014 out->stream.drain = out_drain;
3015 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003016 out->usecase = get_offload_usecase(adev, false);
3017 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003018 }
vivek mehta446c3962015-09-14 10:57:35 -07003019
3020 if (out->usecase == USECASE_INVALID) {
3021 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3022 ret = -EEXIST;
3023 goto error_open;
3024 }
3025
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 if (config->offload_info.channel_mask)
3027 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003028 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003029 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003030 config->offload_info.channel_mask = config->channel_mask;
3031 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003032 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 out->sample_rate = config->offload_info.sample_rate;
3034
Mingming Yin3ee55c62014-08-04 14:23:35 -07003035 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003037 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003038 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003039 audio_extn_dolby_get_snd_codec_id(adev, out,
3040 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003041 else
3042 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003044
3045 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3046 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003047 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003048 platform_get_pcm_offload_buffer_size(&config->offload_info);
3049 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3050 out->compr_config.fragment_size =
3051 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003052 } else {
3053 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003054 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003055 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3057 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003058 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 out->compr_config.codec->bit_rate =
3060 config->offload_info.bit_rate;
3061 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003062 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303064 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003065 /*TODO: Do we need to change it for passthrough */
3066 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067
Manish Dewangana6fc5442015-08-24 20:30:31 +05303068 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3069 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3070 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3071 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003072 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3073 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003074 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003075 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003076 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3077 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003078
Mingming Yin3ee55c62014-08-04 14:23:35 -07003079 if (out->bit_width == 24) {
3080 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3081 }
3082
Amit Shekhar6f461b12014-08-01 14:52:58 -07003083 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303084 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003085
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3087 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003088
Mingming Yin497419f2015-07-01 16:57:32 -07003089 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003090 //this flag is set from framework only if its for PCM formats
3091 //no need to check for PCM format again
3092 out->non_blocking = 0;
3093 out->use_small_bufs = true;
3094 ALOGI("Keep write blocking for small buff: non_blockling %d",
3095 out->non_blocking);
3096 }
3097
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003098 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303099 out->send_next_track_params = false;
3100 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003101 out->offload_state = OFFLOAD_STATE_IDLE;
3102 out->playback_started = 0;
3103
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003104 audio_extn_dts_create_state_notifier_node(out->usecase);
3105
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 create_offload_callback_thread(out);
3107 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3108 __func__, config->offload_info.version,
3109 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003110 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003111 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003112 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3113 ret = voice_check_and_set_incall_music_usecase(adev, out);
3114 if (ret != 0) {
3115 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3116 __func__, ret);
3117 goto error_open;
3118 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003119 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3120 if (config->sample_rate == 0)
3121 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3122 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3123 config->sample_rate != 8000) {
3124 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3125 ret = -EINVAL;
3126 goto error_open;
3127 }
3128 out->sample_rate = config->sample_rate;
3129 out->config.rate = config->sample_rate;
3130 if (config->format == AUDIO_FORMAT_DEFAULT)
3131 config->format = AUDIO_FORMAT_PCM_16_BIT;
3132 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3133 config->format = AUDIO_FORMAT_PCM_16_BIT;
3134 ret = -EINVAL;
3135 goto error_open;
3136 }
3137 out->format = config->format;
3138 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3139 out->config = pcm_config_afe_proxy_playback;
3140 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003141 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3142 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3143 out->config = pcm_config_low_latency;
3144 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003145 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003146 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3148 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003150 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3151 format = AUDIO_FORMAT_PCM_16_BIT;
3152 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3153 out->config = pcm_config_deep_buffer;
3154 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003155 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003156 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003157 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003158 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003159 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003160 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 }
3162
Amit Shekhar1d896042014-10-03 13:16:09 -07003163 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3164 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003165 /* TODO remove this hardcoding and check why width is zero*/
3166 if (out->bit_width == 0)
3167 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003168 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3169 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003170 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303171 out->bit_width, out->channel_mask,
3172 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003173 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3174 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3175 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003176 if(adev->primary_output == NULL)
3177 adev->primary_output = out;
3178 else {
3179 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003180 ret = -EEXIST;
3181 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003182 }
3183 }
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 /* Check if this usecase is already existing */
3186 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003187 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3188 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003191 ret = -EEXIST;
3192 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 }
3194 pthread_mutex_unlock(&adev->lock);
3195
3196 out->stream.common.get_sample_rate = out_get_sample_rate;
3197 out->stream.common.set_sample_rate = out_set_sample_rate;
3198 out->stream.common.get_buffer_size = out_get_buffer_size;
3199 out->stream.common.get_channels = out_get_channels;
3200 out->stream.common.get_format = out_get_format;
3201 out->stream.common.set_format = out_set_format;
3202 out->stream.common.standby = out_standby;
3203 out->stream.common.dump = out_dump;
3204 out->stream.common.set_parameters = out_set_parameters;
3205 out->stream.common.get_parameters = out_get_parameters;
3206 out->stream.common.add_audio_effect = out_add_audio_effect;
3207 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3208 out->stream.get_latency = out_get_latency;
3209 out->stream.set_volume = out_set_volume;
3210 out->stream.write = out_write;
3211 out->stream.get_render_position = out_get_render_position;
3212 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003213 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003216 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003217 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
3219 config->format = out->stream.common.get_format(&out->stream.common);
3220 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3221 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3222
3223 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303224 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003225 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003226
3227 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3228 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3229 popcount(out->channel_mask), out->playback_started);
3230
Eric Laurent994a6932013-07-17 11:51:42 -07003231 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003233
3234error_open:
3235 free(out);
3236 *stream_out = NULL;
3237 ALOGD("%s: exit: ret %d", __func__, ret);
3238 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239}
3240
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003241static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 struct audio_stream_out *stream)
3243{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244 struct stream_out *out = (struct stream_out *)stream;
3245 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003246 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303248 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3249
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003250 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303251 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003252 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303253 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003254 if(ret != 0)
3255 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3256 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003257 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003258 out_standby(&stream->common);
3259
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003260 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003261 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003263 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 if (out->compr_config.codec != NULL)
3265 free(out->compr_config.codec);
3266 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003267
3268 if (adev->voice_tx_output == out)
3269 adev->voice_tx_output = NULL;
3270
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003271 pthread_cond_destroy(&out->cond);
3272 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003274 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003277static void close_compress_sessions(struct audio_device *adev)
3278{
Mingming Yin7b762e72015-03-04 13:47:32 -08003279 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303280 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003281 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003282 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303283
3284 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003285 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303286 if (is_offload_usecase(usecase->id)) {
3287 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003288 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3289 out = usecase->stream.out;
3290 pthread_mutex_unlock(&adev->lock);
3291 out_standby(&out->stream.common);
3292 pthread_mutex_lock(&adev->lock);
3293 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303294 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003295 }
3296 pthread_mutex_unlock(&adev->lock);
3297}
3298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3300{
3301 struct audio_device *adev = (struct audio_device *)dev;
3302 struct str_parms *parms;
3303 char *str;
3304 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003305 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003306 int ret;
3307 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003309 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303312 if (!parms)
3313 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003314 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3315 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303316 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303317 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303318 struct listnode *node;
3319 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303320 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303321 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003322 //close compress sessions on OFFLINE status
3323 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303324 } else if (strstr(snd_card_status, "ONLINE")) {
3325 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303326 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003327 //send dts hpx license if enabled
3328 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303329 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303330 }
3331
3332 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003333 status = voice_set_parameters(adev, parms);
3334 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003335 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003337 status = platform_set_parameters(adev->platform, parms);
3338 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003339 goto done;
3340
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003341 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3342 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003343 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3345 adev->bluetooth_nrec = true;
3346 else
3347 adev->bluetooth_nrec = false;
3348 }
3349
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003350 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3351 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3353 adev->screen_off = false;
3354 else
3355 adev->screen_off = true;
3356 }
3357
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003358 ret = str_parms_get_int(parms, "rotation", &val);
3359 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003360 bool reverse_speakers = false;
3361 switch(val) {
3362 // FIXME: note that the code below assumes that the speakers are in the correct placement
3363 // relative to the user when the device is rotated 90deg from its default rotation. This
3364 // assumption is device-specific, not platform-specific like this code.
3365 case 270:
3366 reverse_speakers = true;
3367 break;
3368 case 0:
3369 case 90:
3370 case 180:
3371 break;
3372 default:
3373 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003374 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003375 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003376 if (status == 0) {
3377 if (adev->speaker_lr_swap != reverse_speakers) {
3378 adev->speaker_lr_swap = reverse_speakers;
3379 // only update the selected device if there is active pcm playback
3380 struct audio_usecase *usecase;
3381 struct listnode *node;
3382 list_for_each(node, &adev->usecase_list) {
3383 usecase = node_to_item(node, struct audio_usecase, list);
3384 if (usecase->type == PCM_PLAYBACK) {
3385 select_devices(adev, usecase->id);
3386 break;
3387 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003388 }
3389 }
3390 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003391 }
3392
Mingming Yin514a8bc2014-07-29 15:22:21 -07003393 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3394 if (ret >= 0) {
3395 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3396 adev->bt_wb_speech_enabled = true;
3397 else
3398 adev->bt_wb_speech_enabled = false;
3399 }
3400
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003401 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3402 if (ret >= 0) {
3403 val = atoi(value);
3404 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3405 ALOGV("cache new edid");
3406 platform_cache_edid(adev->platform);
3407 }
3408 }
3409
3410 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3411 if (ret >= 0) {
3412 val = atoi(value);
3413 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3414 ALOGV("invalidate cached edid");
3415 platform_invalidate_edid(adev->platform);
3416 }
3417 }
3418
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003419 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003420
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003421done:
3422 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003423 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303424error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003425 ALOGV("%s: exit with code(%d)", __func__, status);
3426 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427}
3428
3429static char* adev_get_parameters(const struct audio_hw_device *dev,
3430 const char *keys)
3431{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003432 struct audio_device *adev = (struct audio_device *)dev;
3433 struct str_parms *reply = str_parms_create();
3434 struct str_parms *query = str_parms_create_str(keys);
3435 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303436 char value[256] = {0};
3437 int ret = 0;
3438
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003439 if (!query || !reply) {
3440 ALOGE("adev_get_parameters: failed to create query or reply");
3441 return NULL;
3442 }
3443
Naresh Tannirud7205b62014-06-20 02:54:48 +05303444 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3445 sizeof(value));
3446 if (ret >=0) {
3447 int val = 1;
3448 pthread_mutex_lock(&adev->snd_card_status.lock);
3449 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3450 val = 0;
3451 pthread_mutex_unlock(&adev->snd_card_status.lock);
3452 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3453 goto exit;
3454 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003455
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003456 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003457 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003458 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003459 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303460 pthread_mutex_unlock(&adev->lock);
3461
Naresh Tannirud7205b62014-06-20 02:54:48 +05303462exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003463 str = str_parms_to_str(reply);
3464 str_parms_destroy(query);
3465 str_parms_destroy(reply);
3466
3467 ALOGV("%s: exit: returns - %s", __func__, str);
3468 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469}
3470
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003471static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472{
3473 return 0;
3474}
3475
3476static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3477{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003478 int ret;
3479 struct audio_device *adev = (struct audio_device *)dev;
3480 pthread_mutex_lock(&adev->lock);
3481 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003482 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003483 pthread_mutex_unlock(&adev->lock);
3484 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485}
3486
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003487static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3488 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489{
3490 return -ENOSYS;
3491}
3492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003493static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3494 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
3496 return -ENOSYS;
3497}
3498
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003499static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3500 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501{
3502 return -ENOSYS;
3503}
3504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003505static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3506 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507{
3508 return -ENOSYS;
3509}
3510
3511static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3512{
3513 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 pthread_mutex_lock(&adev->lock);
3516 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003517 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003519 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3520 voice_is_in_call(adev)) {
3521 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003522 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003523 adev->current_call_output = NULL;
3524 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 }
3526 pthread_mutex_unlock(&adev->lock);
3527 return 0;
3528}
3529
3530static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3531{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003532 int ret;
3533
3534 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003535 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003536 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3537 pthread_mutex_unlock(&adev->lock);
3538
3539 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540}
3541
3542static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3543{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003544 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 return 0;
3546}
3547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003548static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 const struct audio_config *config)
3550{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003551 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003553 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3554 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555}
3556
3557static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003558 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 audio_devices_t devices,
3560 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003561 struct audio_stream_in **stream_in,
3562 audio_input_flags_t flags __unused,
3563 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003564 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565{
3566 struct audio_device *adev = (struct audio_device *)dev;
3567 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003568 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003569 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003570 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572 *stream_in = NULL;
3573 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3574 return -EINVAL;
3575
3576 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003577
3578 if (!in) {
3579 ALOGE("failed to allocate input stream");
3580 return -ENOMEM;
3581 }
3582
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303583 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003584 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3585 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003587 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003588 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 in->stream.common.get_sample_rate = in_get_sample_rate;
3591 in->stream.common.set_sample_rate = in_set_sample_rate;
3592 in->stream.common.get_buffer_size = in_get_buffer_size;
3593 in->stream.common.get_channels = in_get_channels;
3594 in->stream.common.get_format = in_get_format;
3595 in->stream.common.set_format = in_set_format;
3596 in->stream.common.standby = in_standby;
3597 in->stream.common.dump = in_dump;
3598 in->stream.common.set_parameters = in_set_parameters;
3599 in->stream.common.get_parameters = in_get_parameters;
3600 in->stream.common.add_audio_effect = in_add_audio_effect;
3601 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3602 in->stream.set_gain = in_set_gain;
3603 in->stream.read = in_read;
3604 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3605
3606 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003607 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 in->standby = 1;
3610 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003611 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003612 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
3614 /* Update config params with the requested sample rate and channels */
3615 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003616 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3617 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3618 is_low_latency = true;
3619#if LOW_LATENCY_CAPTURE_USE_CASE
3620 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3621#endif
3622 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003625 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003627 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303628 if (adev->mode != AUDIO_MODE_IN_CALL) {
3629 ret = -EINVAL;
3630 goto err_open;
3631 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003632 if (config->sample_rate == 0)
3633 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3634 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3635 config->sample_rate != 8000) {
3636 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3637 ret = -EINVAL;
3638 goto err_open;
3639 }
3640 if (config->format == AUDIO_FORMAT_DEFAULT)
3641 config->format = AUDIO_FORMAT_PCM_16_BIT;
3642 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3643 config->format = AUDIO_FORMAT_PCM_16_BIT;
3644 ret = -EINVAL;
3645 goto err_open;
3646 }
3647
3648 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3649 in->config = pcm_config_afe_proxy_record;
3650 in->config.channels = channel_count;
3651 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303652 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3653 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003654 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003655 audio_extn_compr_cap_format_supported(config->format) &&
3656 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003657 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003658 } else {
3659 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003660 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003661 buffer_size = get_input_buffer_size(config->sample_rate,
3662 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003663 channel_count,
3664 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003665 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003666 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3667 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3668 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3669 (in->config.rate == 8000 || in->config.rate == 16000) &&
3670 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3671 voice_extn_compress_voip_open_input_stream(in);
3672 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003675 /* This stream could be for sound trigger lab,
3676 get sound trigger pcm if present */
3677 audio_extn_sound_trigger_check_and_get_session(in);
3678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003680 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003681 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682
3683err_open:
3684 free(in);
3685 *stream_in = NULL;
3686 return ret;
3687}
3688
3689static void adev_close_input_stream(struct audio_hw_device *dev,
3690 struct audio_stream_in *stream)
3691{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003692 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003693 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003694 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303695
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303696 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003697
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303698 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003699 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303700
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003701 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303702 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003703 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303704 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003705 if (ret != 0)
3706 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3707 __func__, ret);
3708 } else
3709 in_standby(&stream->common);
3710
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003711 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003712 audio_extn_ssr_deinit();
3713 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714
Mingming Yine62d7842013-10-25 16:26:03 -07003715 if(audio_extn_compr_cap_enabled() &&
3716 audio_extn_compr_cap_format_supported(in->config.format))
3717 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003718
3719 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 return;
3721}
3722
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003723static int adev_dump(const audio_hw_device_t *device __unused,
3724 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725{
3726 return 0;
3727}
3728
3729static int adev_close(hw_device_t *device)
3730{
3731 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003732
3733 if (!adev)
3734 return 0;
3735
3736 pthread_mutex_lock(&adev_init_lock);
3737
3738 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003739 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003740 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003741 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003742 audio_route_free(adev->audio_route);
3743 free(adev->snd_dev_ref_cnt);
3744 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003745 if (adev->adm_deinit)
3746 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003747 free(device);
3748 adev = NULL;
3749 }
3750 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 return 0;
3753}
3754
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003755/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3756 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3757 * just that it _might_ work.
3758 */
3759static int period_size_is_plausible_for_low_latency(int period_size)
3760{
3761 switch (period_size) {
3762 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003763 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003764 case 240:
3765 case 320:
3766 case 480:
3767 return 1;
3768 default:
3769 return 0;
3770 }
3771}
3772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773static int adev_open(const hw_module_t *module, const char *name,
3774 hw_device_t **device)
3775{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003776 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003778 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3780
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003781 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003782 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003783 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003784 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003785 ALOGD("%s: returning existing instance of adev", __func__);
3786 ALOGD("%s: exit", __func__);
3787 pthread_mutex_unlock(&adev_init_lock);
3788 return 0;
3789 }
3790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 adev = calloc(1, sizeof(struct audio_device));
3792
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003793 if (!adev) {
3794 pthread_mutex_unlock(&adev_init_lock);
3795 return -ENOMEM;
3796 }
3797
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003798 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3801 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3802 adev->device.common.module = (struct hw_module_t *)module;
3803 adev->device.common.close = adev_close;
3804
3805 adev->device.init_check = adev_init_check;
3806 adev->device.set_voice_volume = adev_set_voice_volume;
3807 adev->device.set_master_volume = adev_set_master_volume;
3808 adev->device.get_master_volume = adev_get_master_volume;
3809 adev->device.set_master_mute = adev_set_master_mute;
3810 adev->device.get_master_mute = adev_get_master_mute;
3811 adev->device.set_mode = adev_set_mode;
3812 adev->device.set_mic_mute = adev_set_mic_mute;
3813 adev->device.get_mic_mute = adev_get_mic_mute;
3814 adev->device.set_parameters = adev_set_parameters;
3815 adev->device.get_parameters = adev_get_parameters;
3816 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3817 adev->device.open_output_stream = adev_open_output_stream;
3818 adev->device.close_output_stream = adev_close_output_stream;
3819 adev->device.open_input_stream = adev_open_input_stream;
3820 adev->device.close_input_stream = adev_close_input_stream;
3821 adev->device.dump = adev_dump;
3822
3823 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003825 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003826 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003829 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003830 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003831 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003832 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003833 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003834 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003835 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303836 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303837 adev->perf_lock_opts[0] = 0x101;
3838 adev->perf_lock_opts[1] = 0x20E;
3839 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303840
3841 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3842 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003844 adev->platform = platform_init(adev);
3845 if (!adev->platform) {
3846 free(adev->snd_dev_ref_cnt);
3847 free(adev);
3848 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3849 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003850 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003851 return -EINVAL;
3852 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003853
Naresh Tanniru4c630392014-05-12 01:05:52 +05303854 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3855
Eric Laurentc4aef752013-09-12 17:45:53 -07003856 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3857 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3858 if (adev->visualizer_lib == NULL) {
3859 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3860 } else {
3861 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3862 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003863 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003864 "visualizer_hal_start_output");
3865 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003866 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003867 "visualizer_hal_stop_output");
3868 }
3869 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003870 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003871 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003872
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003873 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3874 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3875 if (adev->offload_effects_lib == NULL) {
3876 ALOGE("%s: DLOPEN failed for %s", __func__,
3877 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3878 } else {
3879 ALOGV("%s: DLOPEN successful for %s", __func__,
3880 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3881 adev->offload_effects_start_output =
3882 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3883 "offload_effects_bundle_hal_start_output");
3884 adev->offload_effects_stop_output =
3885 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3886 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003887 adev->offload_effects_set_hpx_state =
3888 (int (*)(bool))dlsym(adev->offload_effects_lib,
3889 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303890 adev->offload_effects_get_parameters =
3891 (void (*)(struct str_parms *, struct str_parms *))
3892 dlsym(adev->offload_effects_lib,
3893 "offload_effects_bundle_get_parameters");
3894 adev->offload_effects_set_parameters =
3895 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3896 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003897 }
3898 }
3899
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003900 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3901 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3902 if (adev->adm_lib == NULL) {
3903 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3904 } else {
3905 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3906 adev->adm_init = (adm_init_t)
3907 dlsym(adev->adm_lib, "adm_init");
3908 adev->adm_deinit = (adm_deinit_t)
3909 dlsym(adev->adm_lib, "adm_deinit");
3910 adev->adm_register_input_stream = (adm_register_input_stream_t)
3911 dlsym(adev->adm_lib, "adm_register_input_stream");
3912 adev->adm_register_output_stream = (adm_register_output_stream_t)
3913 dlsym(adev->adm_lib, "adm_register_output_stream");
3914 adev->adm_deregister_stream = (adm_deregister_stream_t)
3915 dlsym(adev->adm_lib, "adm_deregister_stream");
3916 adev->adm_request_focus = (adm_request_focus_t)
3917 dlsym(adev->adm_lib, "adm_request_focus");
3918 adev->adm_abandon_focus = (adm_abandon_focus_t)
3919 dlsym(adev->adm_lib, "adm_abandon_focus");
3920 }
3921 }
3922
Mingming Yin514a8bc2014-07-29 15:22:21 -07003923 adev->bt_wb_speech_enabled = false;
3924
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003925 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 *device = &adev->device.common;
3927
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003928 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3929 &adev->streams_output_cfg_list);
3930
Kiran Kandi910e1862013-10-29 13:29:42 -07003931 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003932
3933 char value[PROPERTY_VALUE_MAX];
3934 int trial;
3935 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3936 trial = atoi(value);
3937 if (period_size_is_plausible_for_low_latency(trial)) {
3938 pcm_config_low_latency.period_size = trial;
3939 pcm_config_low_latency.start_threshold = trial / 4;
3940 pcm_config_low_latency.avail_min = trial / 4;
3941 configured_low_latency_capture_period_size = trial;
3942 }
3943 }
3944 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3945 trial = atoi(value);
3946 if (period_size_is_plausible_for_low_latency(trial)) {
3947 configured_low_latency_capture_period_size = trial;
3948 }
3949 }
3950
vivek mehta446c3962015-09-14 10:57:35 -07003951 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003952 pthread_mutex_unlock(&adev_init_lock);
3953
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003954 if (adev->adm_init)
3955 adev->adm_data = adev->adm_init();
3956
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303957 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07003958 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 return 0;
3960}
3961
3962static struct hw_module_methods_t hal_module_methods = {
3963 .open = adev_open,
3964};
3965
3966struct audio_module HAL_MODULE_INFO_SYM = {
3967 .common = {
3968 .tag = HARDWARE_MODULE_TAG,
3969 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3970 .hal_api_version = HARDWARE_HAL_API_VERSION,
3971 .id = AUDIO_HARDWARE_MODULE_ID,
3972 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003973 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003974 .methods = &hal_module_methods,
3975 },
3976};