blob: f8b9652280247e423a576a84fd86c32e6fd3892f [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, 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
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530508
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700509 if (audio_extn_spkr_prot_is_enabled())
510 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 /* start usb playback thread */
512 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
513 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
514 audio_extn_usb_start_playback(adev);
515
516 /* start usb capture thread */
517 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
518 audio_extn_usb_start_capture(adev);
519
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800520 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
521 audio_extn_spkr_prot_is_enabled()) {
522 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 adev->snd_dev_ref_cnt[snd_device]--;
524 return -EINVAL;
525 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200526 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800527 if (audio_extn_spkr_prot_start_processing(snd_device)) {
528 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200529 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800530 return -EINVAL;
531 }
532 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700533 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700534 /* due to the possibility of calibration overwrite between listen
535 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700540 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 return -EINVAL;
547 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300548 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700549 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530550
551 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
552 !adev->native_playback_enabled &&
553 audio_is_true_native_stream_active(adev)) {
554 ALOGD("%s: %d: napb: enabling native mode in hardware",
555 __func__, __LINE__);
556 audio_route_apply_and_update_path(adev->audio_route,
557 "true-native-mode");
558 adev->native_playback_enabled = true;
559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 return 0;
562}
563
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700564int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700565 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
568
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 if (snd_device < SND_DEVICE_MIN ||
570 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800571 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800572 return -EINVAL;
573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
575 ALOGE("%s: device ref cnt is already 0", __func__);
576 return -EINVAL;
577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700580
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
582 ALOGE("%s: Invalid sound device returned", __func__);
583 return -EINVAL;
584 }
585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700587 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800588 /* exit usb play back thread */
589 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
590 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
591 audio_extn_usb_stop_playback();
592
593 /* exit usb capture thread */
594 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700595 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800596
597 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ashish Jain81eb2a82015-05-13 10:52:34 +0530604 if (snd_device == SND_DEVICE_OUT_HDMI)
605 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530606 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
607 adev->native_playback_enabled) {
608 ALOGD("%s: %d: napb: disabling native mode in hardware",
609 __func__, __LINE__);
610 audio_route_reset_and_update_path(adev->audio_route,
611 "true-native-mode");
612 adev->native_playback_enabled = false;
613 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530614
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200615 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700616 audio_extn_sound_trigger_update_device_status(snd_device,
617 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530618 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800619 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622 return 0;
623}
624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625static void check_usecases_codec_backend(struct audio_device *adev,
626 struct audio_usecase *uc_info,
627 snd_device_t snd_device)
628{
629 struct listnode *node;
630 struct audio_usecase *usecase;
631 bool switch_device[AUDIO_USECASE_MAX];
632 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800633 int backend_idx = DEFAULT_CODEC_BACKEND;
634 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635
636 /*
637 * This function is to make sure that all the usecases that are active on
638 * the hardware codec backend are always routed to any one device that is
639 * handled by the hardware codec.
640 * For example, if low-latency and deep-buffer usecases are currently active
641 * on speaker and out_set_parameters(headset) is received on low-latency
642 * output, then we have to make sure deep-buffer is also switched to headset,
643 * because of the limitation that both the devices cannot be enabled
644 * at the same time as they share the same backend.
645 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700646 /*
647 * This call is to check if we need to force routing for a particular stream
648 * If there is a backend configuration change for the device when a
649 * new stream starts, then ADM needs to be closed and re-opened with the new
650 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700652 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
654 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530655
656 ALOGD("%s:becf: force routing %d", __func__, force_routing);
657
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800660 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800661 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 for (i = 0; i < AUDIO_USECASE_MAX; i++)
663 switch_device[i] = false;
664
665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667
668 if (usecase == uc_info)
669 continue;
670 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
673 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
674 __func__, i, backend_idx, usecase_backend_idx,
675 platform_get_snd_device_name(snd_device),
676 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800677
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800678 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700679 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800680 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
681 usecase_backend_idx == backend_idx) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530682 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
683 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700684 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 switch_device[usecase->id] = true;
687 num_uc_to_switch++;
688 }
689 }
690
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
692 num_uc_to_switch);
693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530697 /* Make sure the previous devices to be disabled first and then enable the
698 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 list_for_each(node, &adev->usecase_list) {
700 usecase = node_to_item(node, struct audio_usecase, list);
701 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
704 }
705
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
708 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700710 }
711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 /* Re-route all the usecases on the shared backend other than the
714 specified usecase to new snd devices */
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530717 /* Update the out_snd_device only for the usecases that are enabled here */
718 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
719 usecase->out_snd_device = snd_device;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530720 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
721 use_case_table[usecase->id],
722 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530723 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 }
725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727}
728
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729static void check_and_route_capture_usecases(struct audio_device *adev,
730 struct audio_usecase *uc_info,
731 snd_device_t snd_device)
732{
733 struct listnode *node;
734 struct audio_usecase *usecase;
735 bool switch_device[AUDIO_USECASE_MAX];
736 int i, num_uc_to_switch = 0;
737
738 /*
739 * This function is to make sure that all the active capture usecases
740 * are always routed to the same input sound device.
741 * For example, if audio-record and voice-call usecases are currently
742 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
743 * is received for voice call then we have to make sure that audio-record
744 * usecase is also switched to earpiece i.e. voice-dmic-ef,
745 * because of the limitation that two devices cannot be enabled
746 * at the same time if they share the same backend.
747 */
748 for (i = 0; i < AUDIO_USECASE_MAX; i++)
749 switch_device[i] = false;
750
751 list_for_each(node, &adev->usecase_list) {
752 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800753 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700755 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700756 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
757 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700758 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700759 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
760 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700761 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700762 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 switch_device[usecase->id] = true;
764 num_uc_to_switch++;
765 }
766 }
767
768 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700769 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700770
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530771 /* Make sure the previous devices to be disabled first and then enable the
772 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700773 list_for_each(node, &adev->usecase_list) {
774 usecase = node_to_item(node, struct audio_usecase, list);
775 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700776 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800777 }
778 }
779
780 list_for_each(node, &adev->usecase_list) {
781 usecase = node_to_item(node, struct audio_usecase, list);
782 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700783 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700784 }
785 }
786
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 /* Re-route all the usecases on the shared backend other than the
788 specified usecase to new snd devices */
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
791 /* Update the in_snd_device only before enabling the audio route */
792 if (switch_device[usecase->id] ) {
793 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800794 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530795 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700796 }
797 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700798 }
799}
800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800801/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700802static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800803{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700804 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700805 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806
807 switch (channels) {
808 /*
809 * Do not handle stereo output in Multi-channel cases
810 * Stereo case is handled in normal playback path
811 */
812 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700813 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
814 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
815 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
816 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819 break;
820 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700821 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
822 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
823 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
824 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828 break;
829 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700830 ALOGE("HDMI does not support multi channel playback");
831 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832 break;
833 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700834 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835}
836
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800837audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
838 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700839{
840 struct audio_usecase *usecase;
841 struct listnode *node;
842
843 list_for_each(node, &adev->usecase_list) {
844 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800845 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700846 ALOGV("%s: usecase id %d", __func__, usecase->id);
847 return usecase->id;
848 }
849 }
850 return USECASE_INVALID;
851}
852
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700853struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700854 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855{
856 struct audio_usecase *usecase;
857 struct listnode *node;
858
859 list_for_each(node, &adev->usecase_list) {
860 usecase = node_to_item(node, struct audio_usecase, list);
861 if (usecase->id == uc_id)
862 return usecase;
863 }
864 return NULL;
865}
866
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867/*
868 * is a true native playback active
869 */
870bool audio_is_true_native_stream_active(struct audio_device *adev)
871{
872 bool active = false;
873 int i = 0;
874 struct listnode *node;
875
876 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
877 ALOGV("%s:napb: not in true mode or non hdphones device",
878 __func__);
879 active = false;
880 goto exit;
881 }
882
883 list_for_each(node, &adev->usecase_list) {
884 struct audio_usecase *uc;
885 uc = node_to_item(node, struct audio_usecase, list);
886 struct stream_out *curr_out =
887 (struct stream_out*) uc->stream.out;
888
889 if (curr_out && PCM_PLAYBACK == uc->type) {
890 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
891 "(%d) device %s", __func__, i++, use_case_table[uc->id],
892 uc->id, curr_out->sample_rate,
893 curr_out->bit_width,
894 platform_get_snd_device_name(uc->out_snd_device));
895
896 if (is_offload_usecase(uc->id) &&
897 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
898 active = true;
899 ALOGD("%s:napb:native stream detected", __func__);
900 }
901 }
902 }
903exit:
904 return active;
905}
906
907
908static bool force_device_switch(struct audio_usecase *usecase)
909{
910 bool ret = false;
911 bool is_it_true_mode = false;
912
913 if (is_offload_usecase(usecase->id) &&
914 (usecase->stream.out) &&
915 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
916 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
917 if ((is_it_true_mode && !adev->native_playback_enabled) ||
918 (!is_it_true_mode && adev->native_playback_enabled)){
919 ret = true;
920 ALOGD("napb: time to toggle native mode");
921 }
922 }
923
924 return ret;
925}
926
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700927int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800929 snd_device_t out_snd_device = SND_DEVICE_NONE;
930 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 struct audio_usecase *usecase = NULL;
932 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800933 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800934 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800935 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800936 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700937 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800938
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530939 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 usecase = get_usecase_from_list(adev, uc_id);
942 if (usecase == NULL) {
943 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
944 return -EINVAL;
945 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800947 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800948 (usecase->type == VOIP_CALL) ||
949 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700950 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800951 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 usecase->devices = usecase->stream.out->devices;
954 } else {
955 /*
956 * If the voice call is active, use the sound devices of voice call usecase
957 * so that it would not result any device switch. All the usecases will
958 * be switched to new device when select_devices() is called for voice call
959 * usecase. This is to avoid switching devices for voice call when
960 * check_usecases_codec_backend() is called below.
961 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800962 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700963 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800964 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700965 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
966 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967 in_snd_device = vc_usecase->in_snd_device;
968 out_snd_device = vc_usecase->out_snd_device;
969 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800970 } else if (voice_extn_compress_voip_is_active(adev)) {
971 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700972 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530973 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700974 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800975 in_snd_device = voip_usecase->in_snd_device;
976 out_snd_device = voip_usecase->out_snd_device;
977 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800978 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800979 hfp_ucid = audio_extn_hfp_get_usecase();
980 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700981 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800982 in_snd_device = hfp_usecase->in_snd_device;
983 out_snd_device = hfp_usecase->out_snd_device;
984 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 }
986 if (usecase->type == PCM_PLAYBACK) {
987 usecase->devices = usecase->stream.out->devices;
988 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700989 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700990 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800991 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700992 if (usecase->stream.out == adev->primary_output &&
993 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800994 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700995 select_devices(adev, adev->active_input->usecase);
996 }
997 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 } else if (usecase->type == PCM_CAPTURE) {
999 usecase->devices = usecase->stream.in->device;
1000 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001001 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001002 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001003 if (adev->active_input &&
1004 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301005 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1006 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1007 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001008 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001009 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001010 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1011 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001012 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001013 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001014 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 }
1016 }
1017
1018 if (out_snd_device == usecase->out_snd_device &&
1019 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301020
1021 if (!force_device_switch(usecase))
1022 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 }
1024
sangwoobc677242013-08-08 16:53:43 +09001025 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001026 out_snd_device, platform_get_snd_device_name(out_snd_device),
1027 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 /*
1030 * Limitation: While in call, to do a device switch we need to disable
1031 * and enable both RX and TX devices though one of them is same as current
1032 * device.
1033 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001034 if ((usecase->type == VOICE_CALL) &&
1035 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1036 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001037 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001038 }
1039
1040 if (((usecase->type == VOICE_CALL) ||
1041 (usecase->type == VOIP_CALL)) &&
1042 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1043 /* Disable sidetone only if voice/voip call already exists */
1044 if (voice_is_call_state_active(adev) ||
1045 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001046 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001047 }
1048
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 /* Disable current sound devices */
1050 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001051 disable_audio_route(adev, usecase);
1052 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053 }
1054
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001055 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001056 disable_audio_route(adev, usecase);
1057 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 }
1059
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001060 /* Applicable only on the targets that has external modem.
1061 * New device information should be sent to modem before enabling
1062 * the devices to reduce in-call device switch time.
1063 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001064 if ((usecase->type == VOICE_CALL) &&
1065 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1066 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001067 status = platform_switch_voice_call_enable_device_config(adev->platform,
1068 out_snd_device,
1069 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001070 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001071
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 /* Enable new sound devices */
1073 if (out_snd_device != SND_DEVICE_NONE) {
1074 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1075 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001076 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 }
1078
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001079 if (in_snd_device != SND_DEVICE_NONE) {
1080 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001081 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001082 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083
Avinash Vaish71a8b972014-07-24 15:36:33 +05301084 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001085 status = platform_switch_voice_call_device_post(adev->platform,
1086 out_snd_device,
1087 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301088 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001089 /* Enable sidetone only if voice/voip call already exists */
1090 if (voice_is_call_state_active(adev) ||
1091 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001092 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301093 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001094
sangwoo170731f2013-06-08 15:36:36 +09001095 usecase->in_snd_device = in_snd_device;
1096 usecase->out_snd_device = out_snd_device;
1097
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301098 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001099 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301100 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001101 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301102 usecase->stream.out->flags,
1103 usecase->stream.out->format,
1104 usecase->stream.out->sample_rate,
1105 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301106 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301107 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001108 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301109 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001110
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001111 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001112
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001113 /* Applicable only on the targets that has external modem.
1114 * Enable device command should be sent to modem only after
1115 * enabling voice call mixer controls
1116 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001117 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001118 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1119 out_snd_device,
1120 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301121 ALOGD("%s: done",__func__);
1122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 return status;
1124}
1125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126static int stop_input_stream(struct stream_in *in)
1127{
1128 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129 struct audio_usecase *uc_info;
1130 struct audio_device *adev = in->dev;
1131
Eric Laurentc8400632013-02-14 19:04:54 -08001132 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133
Eric Laurent994a6932013-07-17 11:51:42 -07001134 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136 uc_info = get_usecase_from_list(adev, in->usecase);
1137 if (uc_info == NULL) {
1138 ALOGE("%s: Could not find the usecase (%d) in the list",
1139 __func__, in->usecase);
1140 return -EINVAL;
1141 }
1142
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001143 /* Close in-call recording streams */
1144 voice_check_and_stop_incall_rec_usecase(adev, in);
1145
Eric Laurent150dbfe2013-02-27 14:31:02 -08001146 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001147 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148
1149 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001150 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001152 list_remove(&uc_info->list);
1153 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154
Eric Laurent994a6932013-07-17 11:51:42 -07001155 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156 return ret;
1157}
1158
1159int start_input_stream(struct stream_in *in)
1160{
1161 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001162 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163 struct audio_usecase *uc_info;
1164 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301165 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166
Mingming Yin2664a5b2015-09-03 10:53:11 -07001167 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1168 if (get_usecase_from_list(adev, usecase) == NULL)
1169 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301170 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1171 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001172
Naresh Tanniru80659832014-06-04 18:17:56 +05301173
1174 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301175 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301176 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301177 goto error_config;
1178 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301179
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001180 /* Check if source matches incall recording usecase criteria */
1181 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1182 if (ret)
1183 goto error_config;
1184 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001185 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1186
1187 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1188 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1189 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1190 goto error_config;
1191 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001192
Eric Laurentb23d5282013-05-14 15:27:20 -07001193 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001194 if (in->pcm_device_id < 0) {
1195 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1196 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001197 ret = -EINVAL;
1198 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001200
1201 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001203
1204 if (!uc_info) {
1205 ret = -ENOMEM;
1206 goto error_config;
1207 }
1208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 uc_info->id = in->usecase;
1210 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001211 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 uc_info->devices = in->device;
1213 uc_info->in_snd_device = SND_DEVICE_NONE;
1214 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001216 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301217 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1218 adev->perf_lock_opts,
1219 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221
Eric Laurentc8400632013-02-14 19:04:54 -08001222 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001223 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1224
1225 unsigned int flags = PCM_IN;
1226 unsigned int pcm_open_retry_count = 0;
1227
1228 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1229 flags |= PCM_MMAP | PCM_NOIRQ;
1230 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1231 }
1232
1233 while (1) {
1234 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1235 flags, &in->config);
1236 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1237 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1238 if (in->pcm != NULL) {
1239 pcm_close(in->pcm);
1240 in->pcm = NULL;
1241 }
1242 if (pcm_open_retry_count-- == 0) {
1243 ret = -EIO;
1244 goto error_open;
1245 }
1246 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1247 continue;
1248 }
1249 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001251
1252 ALOGV("%s: pcm_prepare", __func__);
1253 ret = pcm_prepare(in->pcm);
1254 if (ret < 0) {
1255 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1256 pcm_close(in->pcm);
1257 in->pcm = NULL;
1258 goto error_open;
1259 }
1260
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301261 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001262 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001263
Eric Laurentc8400632013-02-14 19:04:54 -08001264 return ret;
1265
1266error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301267 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001269error_config:
1270 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301271 /*
1272 * sleep 50ms to allow sufficient time for kernel
1273 * drivers to recover incases like SSR.
1274 */
1275 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001276 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001277
1278 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279}
1280
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001281void lock_input_stream(struct stream_in *in)
1282{
1283 pthread_mutex_lock(&in->pre_lock);
1284 pthread_mutex_lock(&in->lock);
1285 pthread_mutex_unlock(&in->pre_lock);
1286}
1287
1288void lock_output_stream(struct stream_out *out)
1289{
1290 pthread_mutex_lock(&out->pre_lock);
1291 pthread_mutex_lock(&out->lock);
1292 pthread_mutex_unlock(&out->pre_lock);
1293}
1294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295/* must be called with out->lock locked */
1296static int send_offload_cmd_l(struct stream_out* out, int command)
1297{
1298 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1299
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001300 if (!cmd) {
1301 ALOGE("failed to allocate mem for command 0x%x", command);
1302 return -ENOMEM;
1303 }
1304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 ALOGVV("%s %d", __func__, command);
1306
1307 cmd->cmd = command;
1308 list_add_tail(&out->offload_cmd_list, &cmd->node);
1309 pthread_cond_signal(&out->offload_cond);
1310 return 0;
1311}
1312
1313/* must be called iwth out->lock locked */
1314static void stop_compressed_output_l(struct stream_out *out)
1315{
1316 out->offload_state = OFFLOAD_STATE_IDLE;
1317 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001318 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 if (out->compr != NULL) {
1320 compress_stop(out->compr);
1321 while (out->offload_thread_blocked) {
1322 pthread_cond_wait(&out->cond, &out->lock);
1323 }
1324 }
1325}
1326
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001327bool is_offload_usecase(audio_usecase_t uc_id)
1328{
1329 unsigned int i;
1330 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1331 if (uc_id == offload_usecases[i])
1332 return true;
1333 }
1334 return false;
1335}
1336
vivek mehta446c3962015-09-14 10:57:35 -07001337static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001338{
vivek mehta446c3962015-09-14 10:57:35 -07001339 audio_usecase_t ret_uc = USECASE_INVALID;
1340 unsigned int offload_uc_index;
1341 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1342 if (!adev->multi_offload_enable) {
1343 if (is_direct_pcm)
1344 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1345 else
1346 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001347
vivek mehta446c3962015-09-14 10:57:35 -07001348 pthread_mutex_lock(&adev->lock);
1349 if (get_usecase_from_list(adev, ret_uc) != NULL)
1350 ret_uc = USECASE_INVALID;
1351 pthread_mutex_unlock(&adev->lock);
1352
1353 return ret_uc;
1354 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001355
1356 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001357 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1358 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1359 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1360 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001361 break;
1362 }
1363 }
vivek mehta446c3962015-09-14 10:57:35 -07001364
1365 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1366 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001367}
1368
1369static void free_offload_usecase(struct audio_device *adev,
1370 audio_usecase_t uc_id)
1371{
vivek mehta446c3962015-09-14 10:57:35 -07001372 unsigned int offload_uc_index;
1373 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1374
1375 if (!adev->multi_offload_enable)
1376 return;
1377
1378 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1379 if (offload_usecases[offload_uc_index] == uc_id) {
1380 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001381 break;
1382 }
1383 }
1384 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1385}
1386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001387static void *offload_thread_loop(void *context)
1388{
1389 struct stream_out *out = (struct stream_out *) context;
1390 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001391 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001393 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1394 set_sched_policy(0, SP_FOREGROUND);
1395 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1396
1397 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001398 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001399 for (;;) {
1400 struct offload_cmd *cmd = NULL;
1401 stream_callback_event_t event;
1402 bool send_callback = false;
1403
1404 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1405 __func__, list_empty(&out->offload_cmd_list),
1406 out->offload_state);
1407 if (list_empty(&out->offload_cmd_list)) {
1408 ALOGV("%s SLEEPING", __func__);
1409 pthread_cond_wait(&out->offload_cond, &out->lock);
1410 ALOGV("%s RUNNING", __func__);
1411 continue;
1412 }
1413
1414 item = list_head(&out->offload_cmd_list);
1415 cmd = node_to_item(item, struct offload_cmd, node);
1416 list_remove(item);
1417
1418 ALOGVV("%s STATE %d CMD %d out->compr %p",
1419 __func__, out->offload_state, cmd->cmd, out->compr);
1420
1421 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1422 free(cmd);
1423 break;
1424 }
1425
1426 if (out->compr == NULL) {
1427 ALOGE("%s: Compress handle is NULL", __func__);
1428 pthread_cond_signal(&out->cond);
1429 continue;
1430 }
1431 out->offload_thread_blocked = true;
1432 pthread_mutex_unlock(&out->lock);
1433 send_callback = false;
1434 switch(cmd->cmd) {
1435 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001436 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001437 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001438 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001439 send_callback = true;
1440 event = STREAM_CBK_EVENT_WRITE_READY;
1441 break;
1442 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001443 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301444 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001445 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301446 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001447 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301448 if (ret < 0)
1449 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301450 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301451 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001452 compress_drain(out->compr);
1453 else
1454 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301455 if (ret != -ENETRESET) {
1456 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301457 pthread_mutex_lock(&out->lock);
1458 out->send_new_metadata = 1;
1459 out->send_next_track_params = true;
1460 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301461 event = STREAM_CBK_EVENT_DRAIN_READY;
1462 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1463 } else
1464 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001465 break;
1466 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001467 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001469 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 send_callback = true;
1471 event = STREAM_CBK_EVENT_DRAIN_READY;
1472 break;
1473 default:
1474 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1475 break;
1476 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001477 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001478 out->offload_thread_blocked = false;
1479 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001480 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001481 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001482 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001483 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001484 free(cmd);
1485 }
1486
1487 pthread_cond_signal(&out->cond);
1488 while (!list_empty(&out->offload_cmd_list)) {
1489 item = list_head(&out->offload_cmd_list);
1490 list_remove(item);
1491 free(node_to_item(item, struct offload_cmd, node));
1492 }
1493 pthread_mutex_unlock(&out->lock);
1494
1495 return NULL;
1496}
1497
1498static int create_offload_callback_thread(struct stream_out *out)
1499{
1500 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1501 list_init(&out->offload_cmd_list);
1502 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1503 offload_thread_loop, out);
1504 return 0;
1505}
1506
1507static int destroy_offload_callback_thread(struct stream_out *out)
1508{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001509 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001510 stop_compressed_output_l(out);
1511 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1512
1513 pthread_mutex_unlock(&out->lock);
1514 pthread_join(out->offload_thread, (void **) NULL);
1515 pthread_cond_destroy(&out->offload_cond);
1516
1517 return 0;
1518}
1519
Eric Laurent07eeafd2013-10-06 12:52:49 -07001520static bool allow_hdmi_channel_config(struct audio_device *adev)
1521{
1522 struct listnode *node;
1523 struct audio_usecase *usecase;
1524 bool ret = true;
1525
1526 list_for_each(node, &adev->usecase_list) {
1527 usecase = node_to_item(node, struct audio_usecase, list);
1528 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1529 /*
1530 * If voice call is already existing, do not proceed further to avoid
1531 * disabling/enabling both RX and TX devices, CSD calls, etc.
1532 * Once the voice call done, the HDMI channels can be configured to
1533 * max channels of remaining use cases.
1534 */
1535 if (usecase->id == USECASE_VOICE_CALL) {
1536 ALOGD("%s: voice call is active, no change in HDMI channels",
1537 __func__);
1538 ret = false;
1539 break;
1540 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1541 ALOGD("%s: multi channel playback is active, "
1542 "no change in HDMI channels", __func__);
1543 ret = false;
1544 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001545 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001546 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001547 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1548 ", no change in HDMI channels", __func__,
1549 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001550 ret = false;
1551 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001552 }
1553 }
1554 }
1555 return ret;
1556}
1557
1558static int check_and_set_hdmi_channels(struct audio_device *adev,
1559 unsigned int channels)
1560{
1561 struct listnode *node;
1562 struct audio_usecase *usecase;
1563
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001564 unsigned int supported_channels = platform_edid_get_max_channels(
1565 adev->platform);
1566 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001567 /* Check if change in HDMI channel config is allowed */
1568 if (!allow_hdmi_channel_config(adev))
1569 return 0;
1570
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001571 if (channels > supported_channels)
1572 channels = supported_channels;
1573
Eric Laurent07eeafd2013-10-06 12:52:49 -07001574 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001575 ALOGD("%s: Requested channels are same as current channels(%d)",
1576 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 return 0;
1578 }
1579
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001580 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001581 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001582 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001583 adev->cur_hdmi_channels = channels;
1584
1585 /*
1586 * Deroute all the playback streams routed to HDMI so that
1587 * the back end is deactivated. Note that backend will not
1588 * be deactivated if any one stream is connected to it.
1589 */
1590 list_for_each(node, &adev->usecase_list) {
1591 usecase = node_to_item(node, struct audio_usecase, list);
1592 if (usecase->type == PCM_PLAYBACK &&
1593 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001594 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001595 }
1596 }
1597
1598 /*
1599 * Enable all the streams disabled above. Now the HDMI backend
1600 * will be activated with new channel configuration
1601 */
1602 list_for_each(node, &adev->usecase_list) {
1603 usecase = node_to_item(node, struct audio_usecase, list);
1604 if (usecase->type == PCM_PLAYBACK &&
1605 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001606 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001607 }
1608 }
1609
1610 return 0;
1611}
1612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613static int stop_output_stream(struct stream_out *out)
1614{
1615 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 struct audio_usecase *uc_info;
1617 struct audio_device *adev = out->dev;
1618
Eric Laurent994a6932013-07-17 11:51:42 -07001619 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 uc_info = get_usecase_from_list(adev, out->usecase);
1622 if (uc_info == NULL) {
1623 ALOGE("%s: Could not find the usecase (%d) in the list",
1624 __func__, out->usecase);
1625 return -EINVAL;
1626 }
1627
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001628 if (is_offload_usecase(out->usecase) &&
1629 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001630 if (adev->visualizer_stop_output != NULL)
1631 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001632
1633 audio_extn_dts_remove_state_notifier_node(out->usecase);
1634
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001635 if (adev->offload_effects_stop_output != NULL)
1636 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1637 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001638
Eric Laurent150dbfe2013-02-27 14:31:02 -08001639 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001640 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641
1642 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001643 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001645 list_remove(&uc_info->list);
1646 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001648 if (is_offload_usecase(out->usecase) &&
1649 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1650 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1651 ALOGV("Disable passthrough , reset mixer to pcm");
1652 /* NO_PASSTHROUGH */
1653 out->compr_config.codec->compr_passthr = 0;
1654 audio_extn_dolby_set_hdmi_config(adev, out);
1655 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1656 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001657 /* Must be called after removing the usecase from list */
1658 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1659 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1660
Eric Laurent994a6932013-07-17 11:51:42 -07001661 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 return ret;
1663}
1664
1665int start_output_stream(struct stream_out *out)
1666{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001668 int sink_channels = 0;
1669 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 struct audio_usecase *uc_info;
1671 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301672 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001674 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1675 ret = -EINVAL;
1676 goto error_config;
1677 }
1678
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301679 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1680 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1681 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301682
Naresh Tanniru80659832014-06-04 18:17:56 +05301683 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301684 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301685 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301686 goto error_config;
1687 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301688
Eric Laurentb23d5282013-05-14 15:27:20 -07001689 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690 if (out->pcm_device_id < 0) {
1691 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1692 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001693 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001694 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 }
1696
1697 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001698
1699 if (!uc_info) {
1700 ret = -ENOMEM;
1701 goto error_config;
1702 }
1703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 uc_info->id = out->usecase;
1705 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001706 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 uc_info->devices = out->devices;
1708 uc_info->in_snd_device = SND_DEVICE_NONE;
1709 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001710 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001711 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001712 if (is_offload_usecase(out->usecase)) {
1713 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001714 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1715 }
1716 }
Mingming Yin9c041392014-05-01 15:37:31 -07001717 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1718 if (!strncmp("true", prop_value, 4)) {
1719 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001720 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1721 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001722 check_and_set_hdmi_channels(adev, sink_channels);
1723 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001724 if (is_offload_usecase(out->usecase)) {
1725 unsigned int ch_count = out->compr_config.codec->ch_in;
1726 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1727 /* backend channel config for passthrough stream is stereo */
1728 ch_count = 2;
1729 check_and_set_hdmi_channels(adev, ch_count);
1730 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001731 check_and_set_hdmi_channels(adev, out->config.channels);
1732 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001733 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001734 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001735 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301737 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1738 adev->perf_lock_opts,
1739 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001740 select_devices(adev, out->usecase);
1741
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001742 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1743 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001744 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001745 unsigned int flags = PCM_OUT;
1746 unsigned int pcm_open_retry_count = 0;
1747 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1748 flags |= PCM_MMAP | PCM_NOIRQ;
1749 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1750 } else
1751 flags |= PCM_MONOTONIC;
1752
1753 while (1) {
1754 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1755 flags, &out->config);
1756 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1757 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1758 if (out->pcm != NULL) {
1759 pcm_close(out->pcm);
1760 out->pcm = NULL;
1761 }
1762 if (pcm_open_retry_count-- == 0) {
1763 ret = -EIO;
1764 goto error_open;
1765 }
1766 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1767 continue;
1768 }
1769 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001771
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001772 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1773 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001774
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001775 ALOGV("%s: pcm_prepare", __func__);
1776 if (pcm_is_ready(out->pcm)) {
1777 ret = pcm_prepare(out->pcm);
1778 if (ret < 0) {
1779 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1780 pcm_close(out->pcm);
1781 out->pcm = NULL;
1782 goto error_open;
1783 }
1784 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001786 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1787 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001789 out->compr = compress_open(adev->snd_card,
1790 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 COMPRESS_IN, &out->compr_config);
1792 if (out->compr && !is_compress_ready(out->compr)) {
1793 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1794 compress_close(out->compr);
1795 out->compr = NULL;
1796 ret = -EIO;
1797 goto error_open;
1798 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301799 /* compress_open sends params of the track, so reset the flag here */
1800 out->is_compr_metadata_avail = false;
1801
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001802 if (out->offload_callback)
1803 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001804
Fred Oh3f43e742015-03-04 18:42:34 -08001805 /* Since small bufs uses blocking writes, a write will be blocked
1806 for the default max poll time (20s) in the event of an SSR.
1807 Reduce the poll time to observe and deal with SSR faster.
1808 */
1809 if (out->use_small_bufs) {
1810 compress_set_max_poll_wait(out->compr, 1000);
1811 }
1812
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001813 audio_extn_dts_create_state_notifier_node(out->usecase);
1814 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1815 popcount(out->channel_mask),
1816 out->playback_started);
1817
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001818#ifdef DS1_DOLBY_DDP_ENABLED
1819 if (audio_extn_is_dolby_format(out->format))
1820 audio_extn_dolby_send_ddp_endp_params(adev);
1821#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001822 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1823 if (adev->visualizer_start_output != NULL)
1824 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1825 if (adev->offload_effects_start_output != NULL)
1826 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001827 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001828 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301830 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001831 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001834error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301835 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001837error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301838 /*
1839 * sleep 50ms to allow sufficient time for kernel
1840 * drivers to recover incases like SSR.
1841 */
1842 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001843 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844}
1845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846static int check_input_parameters(uint32_t sample_rate,
1847 audio_format_t format,
1848 int channel_count)
1849{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001850 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001852 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001853 !voice_extn_compress_voip_is_format_supported(format) &&
1854 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001855
1856 switch (channel_count) {
1857 case 1:
1858 case 2:
1859 case 6:
1860 break;
1861 default:
1862 ret = -EINVAL;
1863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
1865 switch (sample_rate) {
1866 case 8000:
1867 case 11025:
1868 case 12000:
1869 case 16000:
1870 case 22050:
1871 case 24000:
1872 case 32000:
1873 case 44100:
1874 case 48000:
1875 break;
1876 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001877 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 }
1879
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001880 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881}
1882
1883static size_t get_input_buffer_size(uint32_t sample_rate,
1884 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001885 int channel_count,
1886 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887{
1888 size_t size = 0;
1889
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001890 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1891 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001893 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001894 if (is_low_latency)
1895 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001896 /* ToDo: should use frame_size computed based on the format and
1897 channel_count here. */
1898 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001900 /* make sure the size is multiple of 32 bytes
1901 * At 48 kHz mono 16-bit PCM:
1902 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1903 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1904 */
1905 size += 0x1f;
1906 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001907
1908 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909}
1910
1911static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1912{
1913 struct stream_out *out = (struct stream_out *)stream;
1914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001915 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916}
1917
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001918static int out_set_sample_rate(struct audio_stream *stream __unused,
1919 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920{
1921 return -ENOSYS;
1922}
1923
1924static size_t out_get_buffer_size(const struct audio_stream *stream)
1925{
1926 struct stream_out *out = (struct stream_out *)stream;
1927
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001928 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001930 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1931 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001933 return out->config.period_size *
1934 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935}
1936
1937static uint32_t out_get_channels(const struct audio_stream *stream)
1938{
1939 struct stream_out *out = (struct stream_out *)stream;
1940
1941 return out->channel_mask;
1942}
1943
1944static audio_format_t out_get_format(const struct audio_stream *stream)
1945{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 struct stream_out *out = (struct stream_out *)stream;
1947
1948 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949}
1950
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001951static int out_set_format(struct audio_stream *stream __unused,
1952 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953{
1954 return -ENOSYS;
1955}
1956
1957static int out_standby(struct audio_stream *stream)
1958{
1959 struct stream_out *out = (struct stream_out *)stream;
1960 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001961
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301962 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1963 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001964 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1965 /* Ignore standby in case of voip call because the voip output
1966 * stream is closed in adev_close_output_stream()
1967 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301968 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001969 return 0;
1970 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001972 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001974 if (adev->adm_deregister_stream)
1975 adev->adm_deregister_stream(adev->adm_data, out->handle);
1976
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001977 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001979 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980 if (out->pcm) {
1981 pcm_close(out->pcm);
1982 out->pcm = NULL;
1983 }
1984 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001985 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001986 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301987 out->send_next_track_params = false;
1988 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001989 out->gapless_mdata.encoder_delay = 0;
1990 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 if (out->compr != NULL) {
1992 compress_close(out->compr);
1993 out->compr = NULL;
1994 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001997 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 }
1999 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002000 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 return 0;
2002}
2003
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002004static int out_dump(const struct audio_stream *stream __unused,
2005 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006{
2007 return 0;
2008}
2009
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002010static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2011{
2012 int ret = 0;
2013 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002014
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002015 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002016 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002017 return -EINVAL;
2018 }
2019
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302020 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002021
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002022 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2023 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302024 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002025 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002026 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2027 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302028 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002029 }
2030
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002031 ALOGV("%s new encoder delay %u and padding %u", __func__,
2032 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2033
2034 return 0;
2035}
2036
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002037static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2038{
2039 return out == adev->primary_output || out == adev->voice_tx_output;
2040}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2043{
2044 struct stream_out *out = (struct stream_out *)stream;
2045 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002046 struct audio_usecase *usecase;
2047 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 struct str_parms *parms;
2049 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002050 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002051 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
sangwoobc677242013-08-08 16:53:43 +09002053 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302056 if (!parms)
2057 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002058 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2059 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002061 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002062 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002064 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302065 * When HDMI cable is unplugged/usb hs is disconnected the
2066 * music playback is paused and the policy manager sends routing=0
2067 * But the audioflingercontinues to write data until standby time
2068 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 * Avoid this by routing audio to speaker until standby.
2070 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302071 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2072 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002073 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002074 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2075 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 }
2077
2078 /*
2079 * select_devices() call below switches all the usecases on the same
2080 * backend to the new device. Refer to check_usecases_codec_backend() in
2081 * the select_devices(). But how do we undo this?
2082 *
2083 * For example, music playback is active on headset (deep-buffer usecase)
2084 * and if we go to ringtones and select a ringtone, low-latency usecase
2085 * will be started on headset+speaker. As we can't enable headset+speaker
2086 * and headset devices at the same time, select_devices() switches the music
2087 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2088 * So when the ringtone playback is completed, how do we undo the same?
2089 *
2090 * We are relying on the out_set_parameters() call on deep-buffer output,
2091 * once the ringtone playback is ended.
2092 * NOTE: We should not check if the current devices are same as new devices.
2093 * Because select_devices() must be called to switch back the music
2094 * playback to headset.
2095 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002096 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002097 out->devices = val;
2098
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302099 if (!out->standby) {
2100 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2101 adev->perf_lock_opts,
2102 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002103 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302104 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2105 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002107 if (output_drives_call(adev, out)) {
2108 if(!voice_is_in_call(adev)) {
2109 if (adev->mode == AUDIO_MODE_IN_CALL) {
2110 adev->current_call_output = out;
2111 ret = voice_start_call(adev);
2112 }
2113 } else {
2114 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002115 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002116 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002117 }
2118 }
2119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002121 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002123
2124 if (out == adev->primary_output) {
2125 pthread_mutex_lock(&adev->lock);
2126 audio_extn_set_parameters(adev, parms);
2127 pthread_mutex_unlock(&adev->lock);
2128 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002129 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002130 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002131 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002132
2133 audio_extn_dts_create_state_notifier_node(out->usecase);
2134 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2135 popcount(out->channel_mask),
2136 out->playback_started);
2137
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002138 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002139 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302142error:
Eric Laurent994a6932013-07-17 11:51:42 -07002143 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 return ret;
2145}
2146
2147static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2148{
2149 struct stream_out *out = (struct stream_out *)stream;
2150 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002151 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 char value[256];
2153 struct str_parms *reply = str_parms_create();
2154 size_t i, j;
2155 int ret;
2156 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002157
2158 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002159 if (reply) {
2160 str_parms_destroy(reply);
2161 }
2162 if (query) {
2163 str_parms_destroy(query);
2164 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002165 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2166 return NULL;
2167 }
2168
Eric Laurent994a6932013-07-17 11:51:42 -07002169 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2171 if (ret >= 0) {
2172 value[0] = '\0';
2173 i = 0;
2174 while (out->supported_channel_masks[i] != 0) {
2175 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2176 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2177 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002178 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002180 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 first = false;
2182 break;
2183 }
2184 }
2185 i++;
2186 }
2187 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2188 str = str_parms_to_str(reply);
2189 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002190 voice_extn_out_get_parameters(out, query, reply);
2191 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002192 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002193 free(str);
2194 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002197
Alexy Joseph62142aa2015-11-16 15:10:34 -08002198
2199 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2200 if (ret >= 0) {
2201 value[0] = '\0';
2202 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2203 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302204 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002205 } else {
2206 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302207 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002208 }
2209 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002210 if (str)
2211 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002212 str = str_parms_to_str(reply);
2213 }
2214
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002215 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2216 if (ret >= 0) {
2217 value[0] = '\0';
2218 i = 0;
2219 first = true;
2220 while (out->supported_formats[i] != 0) {
2221 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2222 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2223 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002224 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002225 }
2226 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2227 first = false;
2228 break;
2229 }
2230 }
2231 i++;
2232 }
2233 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002234 if (str)
2235 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002236 str = str_parms_to_str(reply);
2237 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 str_parms_destroy(query);
2239 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002240 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 return str;
2242}
2243
2244static uint32_t out_get_latency(const struct audio_stream_out *stream)
2245{
2246 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002247 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248
Alexy Josephaa54c872014-12-03 02:46:47 -08002249 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002250 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002251 } else {
2252 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002254 }
2255
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302256 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002257 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258}
2259
2260static int out_set_volume(struct audio_stream_out *stream, float left,
2261 float right)
2262{
Eric Laurenta9024de2013-04-04 09:19:12 -07002263 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002264 int volume[2];
2265
Eric Laurenta9024de2013-04-04 09:19:12 -07002266 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2267 /* only take left channel into account: the API is for stereo anyway */
2268 out->muted = (left == 0.0f);
2269 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002270 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002271 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2272 /*
2273 * Set mute or umute on HDMI passthrough stream.
2274 * Only take left channel into account.
2275 * Mute is 0 and unmute 1
2276 */
2277 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2278 } else {
2279 char mixer_ctl_name[128];
2280 struct audio_device *adev = out->dev;
2281 struct mixer_ctl *ctl;
2282 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002283 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002285 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2286 "Compress Playback %d Volume", pcm_device_id);
2287 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2288 if (!ctl) {
2289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2290 __func__, mixer_ctl_name);
2291 return -EINVAL;
2292 }
2293 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2294 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2295 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2296 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002297 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002298 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 return -ENOSYS;
2301}
2302
2303static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2304 size_t bytes)
2305{
2306 struct stream_out *out = (struct stream_out *)stream;
2307 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302308 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002309 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002311 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302312
Naresh Tanniru80659832014-06-04 18:17:56 +05302313 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002314 // increase written size during SSR to avoid mismatch
2315 // with the written frames count in AF
2316 if (!is_offload_usecase(out->usecase))
2317 out->written += bytes / (out->config.channels * sizeof(short));
2318
Naresh Tanniru80659832014-06-04 18:17:56 +05302319 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302320 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302321 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302322 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002323 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302324 //during SSR for compress usecase we should return error to flinger
2325 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2326 pthread_mutex_unlock(&out->lock);
2327 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302328 }
2329 }
2330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002332 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002333 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002334 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2335 ret = voice_extn_compress_voip_start_output_stream(out);
2336 else
2337 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002338 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002339 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002341 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342 goto exit;
2343 }
vivek mehta446c3962015-09-14 10:57:35 -07002344 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002345 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347
Ashish Jain81eb2a82015-05-13 10:52:34 +05302348 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2349 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2350 adev->is_channel_status_set = true;
2351 }
2352
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002353 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002354 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002355 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002356 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002357 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2358 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302359 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2360 ALOGD("copl(%p):send next track params in gapless", out);
2361 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2362 out->send_next_track_params = false;
2363 out->is_compr_metadata_avail = false;
2364 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002365 }
2366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302368 if (ret < 0)
2369 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002371 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302372 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302374 } else if (-ENETRESET == ret) {
2375 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2376 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2377 pthread_mutex_unlock(&out->lock);
2378 out_standby(&out->stream.common);
2379 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302381 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002382 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002383 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 out->playback_started = 1;
2385 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002386
2387 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2388 popcount(out->channel_mask),
2389 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 }
2391 pthread_mutex_unlock(&out->lock);
2392 return ret;
2393 } else {
2394 if (out->pcm) {
2395 if (out->muted)
2396 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002397
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002399
2400 if (adev->adm_request_focus)
2401 adev->adm_request_focus(adev->adm_data, out->handle);
2402
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002403 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2404 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2405 else
2406 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002407
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302408 if (ret < 0)
2409 ret = -errno;
2410 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002411 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002412
2413 if (adev->adm_abandon_focus)
2414 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 }
2417
2418exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302419 /* ToDo: There may be a corner case when SSR happens back to back during
2420 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302421 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302422 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302423 }
2424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 pthread_mutex_unlock(&out->lock);
2426
2427 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002428 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002429 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302430 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302431 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302432 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302433 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302434 out->standby = true;
2435 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002437 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302438 out_get_sample_rate(&out->stream.common));
2439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 }
2441 return bytes;
2442}
2443
2444static int out_get_render_position(const struct audio_stream_out *stream,
2445 uint32_t *dsp_frames)
2446{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302448 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002449
2450 if (dsp_frames == NULL)
2451 return -EINVAL;
2452
2453 *dsp_frames = 0;
2454 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002455 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002456 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302458 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302460 if (ret < 0)
2461 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 ALOGVV("%s rendered frames %d sample_rate %d",
2463 __func__, *dsp_frames, out->sample_rate);
2464 }
2465 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302466 if (-ENETRESET == ret) {
2467 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2468 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2469 return -EINVAL;
2470 } else if(ret < 0) {
2471 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2472 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302473 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2474 /*
2475 * Handle corner case where compress session is closed during SSR
2476 * and timestamp is queried
2477 */
2478 ALOGE(" ERROR: sound card not active, return error");
2479 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302480 } else {
2481 return 0;
2482 }
Zhou Song32a556e2015-05-05 10:46:56 +08002483 } else if (audio_is_linear_pcm(out->format)) {
2484 *dsp_frames = out->written;
2485 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486 } else
2487 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488}
2489
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002490static int out_add_audio_effect(const struct audio_stream *stream __unused,
2491 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492{
2493 return 0;
2494}
2495
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002496static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2497 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498{
2499 return 0;
2500}
2501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002502static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2503 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504{
2505 return -EINVAL;
2506}
2507
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002508static int out_get_presentation_position(const struct audio_stream_out *stream,
2509 uint64_t *frames, struct timespec *timestamp)
2510{
2511 struct stream_out *out = (struct stream_out *)stream;
2512 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002513 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002514
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002515 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002516
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002517 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002518 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302519 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002520 &out->sample_rate);
2521 ALOGVV("%s rendered frames %ld sample_rate %d",
2522 __func__, dsp_frames, out->sample_rate);
2523 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302524 if (ret < 0)
2525 ret = -errno;
2526 if (-ENETRESET == ret) {
2527 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2528 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2529 ret = -EINVAL;
2530 } else
2531 ret = 0;
2532
Eric Laurent949a0892013-09-20 09:20:13 -07002533 /* this is the best we can do */
2534 clock_gettime(CLOCK_MONOTONIC, timestamp);
2535 }
2536 } else {
2537 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002538 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002539 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2540 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002541 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002542 // This adjustment accounts for buffering after app processor.
2543 // It is based on estimated DSP latency per use case, rather than exact.
2544 signed_frames -=
2545 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2546
Eric Laurent949a0892013-09-20 09:20:13 -07002547 // It would be unusual for this value to be negative, but check just in case ...
2548 if (signed_frames >= 0) {
2549 *frames = signed_frames;
2550 ret = 0;
2551 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002552 }
2553 }
2554 }
2555
2556 pthread_mutex_unlock(&out->lock);
2557
2558 return ret;
2559}
2560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002561static int out_set_callback(struct audio_stream_out *stream,
2562 stream_callback_t callback, void *cookie)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565
2566 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002567 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002568 out->offload_callback = callback;
2569 out->offload_cookie = cookie;
2570 pthread_mutex_unlock(&out->lock);
2571 return 0;
2572}
2573
2574static int out_pause(struct audio_stream_out* stream)
2575{
2576 struct stream_out *out = (struct stream_out *)stream;
2577 int status = -ENOSYS;
2578 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002579 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002580 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002581 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302583 struct audio_device *adev = out->dev;
2584 int snd_scard_state = get_snd_card_state(adev);
2585
2586 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2587 status = compress_pause(out->compr);
2588
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002590
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302591 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002592 audio_extn_dts_notify_playback_state(out->usecase, 0,
2593 out->sample_rate, popcount(out->channel_mask),
2594 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 }
2596 pthread_mutex_unlock(&out->lock);
2597 }
2598 return status;
2599}
2600
2601static int out_resume(struct audio_stream_out* stream)
2602{
2603 struct stream_out *out = (struct stream_out *)stream;
2604 int status = -ENOSYS;
2605 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002606 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002607 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002609 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002610 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302611 struct audio_device *adev = out->dev;
2612 int snd_scard_state = get_snd_card_state(adev);
2613
2614 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2615 status = compress_resume(out->compr);
2616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002618
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302619 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002620 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2621 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 }
2623 pthread_mutex_unlock(&out->lock);
2624 }
2625 return status;
2626}
2627
2628static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2629{
2630 struct stream_out *out = (struct stream_out *)stream;
2631 int status = -ENOSYS;
2632 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002633 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002634 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002635 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2636 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2637 else
2638 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2639 pthread_mutex_unlock(&out->lock);
2640 }
2641 return status;
2642}
2643
2644static int out_flush(struct audio_stream_out* stream)
2645{
2646 struct stream_out *out = (struct stream_out *)stream;
2647 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002648 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002649 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002650 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002651 stop_compressed_output_l(out);
2652 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002653 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002654 return 0;
2655 }
2656 return -ENOSYS;
2657}
2658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659/** audio_stream_in implementation **/
2660static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2661{
2662 struct stream_in *in = (struct stream_in *)stream;
2663
2664 return in->config.rate;
2665}
2666
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002667static int in_set_sample_rate(struct audio_stream *stream __unused,
2668 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669{
2670 return -ENOSYS;
2671}
2672
2673static size_t in_get_buffer_size(const struct audio_stream *stream)
2674{
2675 struct stream_in *in = (struct stream_in *)stream;
2676
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002677 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2678 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002679 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2680 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002681
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002682 return in->config.period_size *
2683 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684}
2685
2686static uint32_t in_get_channels(const struct audio_stream *stream)
2687{
2688 struct stream_in *in = (struct stream_in *)stream;
2689
2690 return in->channel_mask;
2691}
2692
2693static audio_format_t in_get_format(const struct audio_stream *stream)
2694{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002695 struct stream_in *in = (struct stream_in *)stream;
2696
2697 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698}
2699
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002700static int in_set_format(struct audio_stream *stream __unused,
2701 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702{
2703 return -ENOSYS;
2704}
2705
2706static int in_standby(struct audio_stream *stream)
2707{
2708 struct stream_in *in = (struct stream_in *)stream;
2709 struct audio_device *adev = in->dev;
2710 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302711 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2712 stream, in->usecase, use_case_table[in->usecase]);
2713
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002714 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2715 /* Ignore standby in case of voip call because the voip input
2716 * stream is closed in adev_close_input_stream()
2717 */
2718 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2719 return status;
2720 }
2721
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002722 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002723 if (!in->standby && in->is_st_session) {
2724 ALOGD("%s: sound trigger pcm stop lab", __func__);
2725 audio_extn_sound_trigger_stop_lab(in);
2726 in->standby = 1;
2727 }
2728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002730 if (adev->adm_deregister_stream)
2731 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2732
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002733 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002735 if (in->pcm) {
2736 pcm_close(in->pcm);
2737 in->pcm = NULL;
2738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002740 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 }
2742 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002743 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 return status;
2745}
2746
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002747static int in_dump(const struct audio_stream *stream __unused,
2748 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749{
2750 return 0;
2751}
2752
2753static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2754{
2755 struct stream_in *in = (struct stream_in *)stream;
2756 struct audio_device *adev = in->dev;
2757 struct str_parms *parms;
2758 char *str;
2759 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002760 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302762 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 parms = str_parms_create_str(kvpairs);
2764
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302765 if (!parms)
2766 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002767 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002768 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002769
2770 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2771 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 val = atoi(value);
2773 /* no audio source uses val == 0 */
2774 if ((in->source != val) && (val != 0)) {
2775 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002776 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2777 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2778 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2779 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002780 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002781 err = voice_extn_compress_voip_open_input_stream(in);
2782 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002783 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002784 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002785 }
2786 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 }
2788 }
2789
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002790 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2791 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002793 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 in->device = val;
2795 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002796 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002797 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 }
2799 }
2800
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002801done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002803 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804
2805 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302806error:
Eric Laurent994a6932013-07-17 11:51:42 -07002807 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 return ret;
2809}
2810
2811static char* in_get_parameters(const struct audio_stream *stream,
2812 const char *keys)
2813{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002814 struct stream_in *in = (struct stream_in *)stream;
2815 struct str_parms *query = str_parms_create_str(keys);
2816 char *str;
2817 char value[256];
2818 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002819
2820 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002821 if (reply) {
2822 str_parms_destroy(reply);
2823 }
2824 if (query) {
2825 str_parms_destroy(query);
2826 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002827 ALOGE("in_get_parameters: failed to create query or reply");
2828 return NULL;
2829 }
2830
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002831 ALOGV("%s: enter: keys - %s", __func__, keys);
2832
2833 voice_extn_in_get_parameters(in, query, reply);
2834
2835 str = str_parms_to_str(reply);
2836 str_parms_destroy(query);
2837 str_parms_destroy(reply);
2838
2839 ALOGV("%s: exit: returns - %s", __func__, str);
2840 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841}
2842
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002843static int in_set_gain(struct audio_stream_in *stream __unused,
2844 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845{
2846 return 0;
2847}
2848
2849static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2850 size_t bytes)
2851{
2852 struct stream_in *in = (struct stream_in *)stream;
2853 struct audio_device *adev = in->dev;
2854 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302855 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002857 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302858
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002859 if (in->is_st_session) {
2860 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2861 /* Read from sound trigger HAL */
2862 audio_extn_sound_trigger_read(in, buffer, bytes);
2863 pthread_mutex_unlock(&in->lock);
2864 return bytes;
2865 }
2866
2867 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2868 ALOGD(" %s: sound card is not active/SSR state", __func__);
2869 ret= -EIO;;
2870 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302871 }
2872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002874 pthread_mutex_lock(&adev->lock);
2875 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2876 ret = voice_extn_compress_voip_start_input_stream(in);
2877 else
2878 ret = start_input_stream(in);
2879 pthread_mutex_unlock(&adev->lock);
2880 if (ret != 0) {
2881 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 }
2883 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002884 if (adev->adm_register_input_stream)
2885 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002888 if (adev->adm_request_focus)
2889 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002892 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002893 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002894 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2895 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002896 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2897 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002898 else
2899 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302900 if (ret < 0)
2901 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 }
2903
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002904 if (adev->adm_abandon_focus)
2905 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 /*
2908 * Instead of writing zeroes here, we could trust the hardware
2909 * to always provide zeroes when muted.
2910 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302911 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2912 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 memset(buffer, 0, bytes);
2914
2915exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302916 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302917 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002918 if (-ENETRESET == ret)
2919 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 pthread_mutex_unlock(&in->lock);
2922
2923 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302924 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302925 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302926 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302927 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302928 in->standby = true;
2929 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302930 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002932 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002933 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302934 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 }
2936 return bytes;
2937}
2938
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002939static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940{
2941 return 0;
2942}
2943
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002944static int add_remove_audio_effect(const struct audio_stream *stream,
2945 effect_handle_t effect,
2946 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002948 struct stream_in *in = (struct stream_in *)stream;
2949 int status = 0;
2950 effect_descriptor_t desc;
2951
2952 status = (*effect)->get_descriptor(effect, &desc);
2953 if (status != 0)
2954 return status;
2955
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002956 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002957 pthread_mutex_lock(&in->dev->lock);
2958 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2959 in->enable_aec != enable &&
2960 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2961 in->enable_aec = enable;
2962 if (!in->standby)
2963 select_devices(in->dev, in->usecase);
2964 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002965 if (in->enable_ns != enable &&
2966 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2967 in->enable_ns = enable;
2968 if (!in->standby)
2969 select_devices(in->dev, in->usecase);
2970 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002971 pthread_mutex_unlock(&in->dev->lock);
2972 pthread_mutex_unlock(&in->lock);
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 return 0;
2975}
2976
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002977static int in_add_audio_effect(const struct audio_stream *stream,
2978 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979{
Eric Laurent994a6932013-07-17 11:51:42 -07002980 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002981 return add_remove_audio_effect(stream, effect, true);
2982}
2983
2984static int in_remove_audio_effect(const struct audio_stream *stream,
2985 effect_handle_t effect)
2986{
Eric Laurent994a6932013-07-17 11:51:42 -07002987 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002988 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989}
2990
2991static int adev_open_output_stream(struct audio_hw_device *dev,
2992 audio_io_handle_t handle,
2993 audio_devices_t devices,
2994 audio_output_flags_t flags,
2995 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002996 struct audio_stream_out **stream_out,
2997 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998{
2999 struct audio_device *adev = (struct audio_device *)dev;
3000 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003001 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003002 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303005
3006 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3007 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003008 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303009 return -EINVAL;
3010 }
3011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3013
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303014 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3015 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3016 devices, flags, &out->stream);
3017
3018
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003019 if (!out) {
3020 return -ENOMEM;
3021 }
3022
Haynes Mathew George204045b2015-02-25 20:32:03 -08003023 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003024 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003025 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 if (devices == AUDIO_DEVICE_NONE)
3028 devices = AUDIO_DEVICE_OUT_SPEAKER;
3029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 out->flags = flags;
3031 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003032 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003033 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034 out->sample_rate = config->sample_rate;
3035 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3036 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003037 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003038 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003039 out->non_blocking = 0;
3040 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041
3042 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003043 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303044 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3045 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003046 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3047 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3048
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003049 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003050 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3051 ret = read_hdmi_channel_masks(out);
3052
3053 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3054 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003055 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003056 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003057 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003058
3059 if (config->sample_rate == 0)
3060 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3061 if (config->channel_mask == 0)
3062 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3063
3064 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3067 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003069 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003071 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3072 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003073 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003074 ret = voice_extn_compress_voip_open_output_stream(out);
3075 if (ret != 0) {
3076 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3077 __func__, ret);
3078 goto error_open;
3079 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003080 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3081 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3082
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3084 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3085 ALOGE("%s: Unsupported Offload information", __func__);
3086 ret = -EINVAL;
3087 goto error_open;
3088 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003089
3090 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3091 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3092 ALOGV("read and update_pass through formats");
3093 ret = audio_extn_dolby_update_passt_formats(adev, out);
3094 if(ret != 0) {
3095 goto error_open;
3096 }
3097 if(config->offload_info.format == 0)
3098 config->offload_info.format = out->supported_formats[0];
3099 }
3100
Mingming Yin90310102013-11-13 16:57:00 -08003101 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003102 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003103 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003104 ret = -EINVAL;
3105 goto error_open;
3106 }
3107
3108 out->compr_config.codec = (struct snd_codec *)
3109 calloc(1, sizeof(struct snd_codec));
3110
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003111 if (!out->compr_config.codec) {
3112 ret = -ENOMEM;
3113 goto error_open;
3114 }
3115
vivek mehta0ea887a2015-08-26 14:01:20 -07003116 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003117 out->usecase = get_offload_usecase(adev, true);
3118 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003119 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003120 out->stream.set_callback = out_set_callback;
3121 out->stream.pause = out_pause;
3122 out->stream.resume = out_resume;
3123 out->stream.drain = out_drain;
3124 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003125 out->usecase = get_offload_usecase(adev, false);
3126 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003127 }
vivek mehta446c3962015-09-14 10:57:35 -07003128
3129 if (out->usecase == USECASE_INVALID) {
3130 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3131 ret = -EEXIST;
3132 goto error_open;
3133 }
3134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 if (config->offload_info.channel_mask)
3136 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003137 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003138 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003139 config->offload_info.channel_mask = config->channel_mask;
3140 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003141 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 out->sample_rate = config->offload_info.sample_rate;
3143
Mingming Yin3ee55c62014-08-04 14:23:35 -07003144 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003146 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003147 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003148 audio_extn_dolby_get_snd_codec_id(adev, out,
3149 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003150 else
3151 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003153
3154 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3155 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003156 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003157 platform_get_pcm_offload_buffer_size(&config->offload_info);
3158 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3159 out->compr_config.fragment_size =
3160 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003161 } else {
3162 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003163 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003164 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003165 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3166 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003167 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003168 out->compr_config.codec->bit_rate =
3169 config->offload_info.bit_rate;
3170 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303173 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003174 /*TODO: Do we need to change it for passthrough */
3175 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003176
Manish Dewangana6fc5442015-08-24 20:30:31 +05303177 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3178 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3179 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3180 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003181 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3182 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003183 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003184 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003185 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3186 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003187
Mingming Yin3ee55c62014-08-04 14:23:35 -07003188 if (out->bit_width == 24) {
3189 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3190 }
3191
Amit Shekhar6f461b12014-08-01 14:52:58 -07003192 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303193 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003194
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003195 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3196 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003197
Mingming Yin497419f2015-07-01 16:57:32 -07003198 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003199 //this flag is set from framework only if its for PCM formats
3200 //no need to check for PCM format again
3201 out->non_blocking = 0;
3202 out->use_small_bufs = true;
3203 ALOGI("Keep write blocking for small buff: non_blockling %d",
3204 out->non_blocking);
3205 }
3206
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003207 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303208 out->send_next_track_params = false;
3209 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003210 out->offload_state = OFFLOAD_STATE_IDLE;
3211 out->playback_started = 0;
3212
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003213 audio_extn_dts_create_state_notifier_node(out->usecase);
3214
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 create_offload_callback_thread(out);
3216 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3217 __func__, config->offload_info.version,
3218 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003219 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003220 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003221 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3222 ret = voice_check_and_set_incall_music_usecase(adev, out);
3223 if (ret != 0) {
3224 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3225 __func__, ret);
3226 goto error_open;
3227 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3229 if (config->sample_rate == 0)
3230 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3231 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3232 config->sample_rate != 8000) {
3233 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3234 ret = -EINVAL;
3235 goto error_open;
3236 }
3237 out->sample_rate = config->sample_rate;
3238 out->config.rate = config->sample_rate;
3239 if (config->format == AUDIO_FORMAT_DEFAULT)
3240 config->format = AUDIO_FORMAT_PCM_16_BIT;
3241 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3242 config->format = AUDIO_FORMAT_PCM_16_BIT;
3243 ret = -EINVAL;
3244 goto error_open;
3245 }
3246 out->format = config->format;
3247 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3248 out->config = pcm_config_afe_proxy_playback;
3249 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003250 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3251 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3252 out->config = pcm_config_low_latency;
3253 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003254 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003255 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3257 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003258 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003259 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3260 format = AUDIO_FORMAT_PCM_16_BIT;
3261 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3262 out->config = pcm_config_deep_buffer;
3263 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003264 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003265 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003266 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003267 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003268 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003269 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 }
3271
Amit Shekhar1d896042014-10-03 13:16:09 -07003272 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3273 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003274 /* TODO remove this hardcoding and check why width is zero*/
3275 if (out->bit_width == 0)
3276 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003277 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3278 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003279 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303280 out->bit_width, out->channel_mask,
3281 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003282 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3283 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3284 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003285 if(adev->primary_output == NULL)
3286 adev->primary_output = out;
3287 else {
3288 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003289 ret = -EEXIST;
3290 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003291 }
3292 }
3293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294 /* Check if this usecase is already existing */
3295 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003296 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3297 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003300 ret = -EEXIST;
3301 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 }
3303 pthread_mutex_unlock(&adev->lock);
3304
3305 out->stream.common.get_sample_rate = out_get_sample_rate;
3306 out->stream.common.set_sample_rate = out_set_sample_rate;
3307 out->stream.common.get_buffer_size = out_get_buffer_size;
3308 out->stream.common.get_channels = out_get_channels;
3309 out->stream.common.get_format = out_get_format;
3310 out->stream.common.set_format = out_set_format;
3311 out->stream.common.standby = out_standby;
3312 out->stream.common.dump = out_dump;
3313 out->stream.common.set_parameters = out_set_parameters;
3314 out->stream.common.get_parameters = out_get_parameters;
3315 out->stream.common.add_audio_effect = out_add_audio_effect;
3316 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3317 out->stream.get_latency = out_get_latency;
3318 out->stream.set_volume = out_set_volume;
3319 out->stream.write = out_write;
3320 out->stream.get_render_position = out_get_render_position;
3321 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003322 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003325 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003326 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327
3328 config->format = out->stream.common.get_format(&out->stream.common);
3329 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3330 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3331
3332 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303333 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003334 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003335
3336 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3337 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3338 popcount(out->channel_mask), out->playback_started);
3339
Eric Laurent994a6932013-07-17 11:51:42 -07003340 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003342
3343error_open:
3344 free(out);
3345 *stream_out = NULL;
3346 ALOGD("%s: exit: ret %d", __func__, ret);
3347 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348}
3349
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003350static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 struct audio_stream_out *stream)
3352{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 struct stream_out *out = (struct stream_out *)stream;
3354 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003355 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303357 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3358
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003359 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303360 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003361 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303362 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003363 if(ret != 0)
3364 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3365 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003366 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003367 out_standby(&stream->common);
3368
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003369 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003370 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003372 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 if (out->compr_config.codec != NULL)
3374 free(out->compr_config.codec);
3375 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003376
3377 if (adev->voice_tx_output == out)
3378 adev->voice_tx_output = NULL;
3379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 pthread_cond_destroy(&out->cond);
3381 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003383 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384}
3385
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003386static void close_compress_sessions(struct audio_device *adev)
3387{
Mingming Yin7b762e72015-03-04 13:47:32 -08003388 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303389 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003390 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003391 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303392
3393 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003394 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303395 if (is_offload_usecase(usecase->id)) {
3396 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003397 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3398 out = usecase->stream.out;
3399 pthread_mutex_unlock(&adev->lock);
3400 out_standby(&out->stream.common);
3401 pthread_mutex_lock(&adev->lock);
3402 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303403 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003404 }
3405 pthread_mutex_unlock(&adev->lock);
3406}
3407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3409{
3410 struct audio_device *adev = (struct audio_device *)dev;
3411 struct str_parms *parms;
3412 char *str;
3413 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003414 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003415 int ret;
3416 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003418 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303421 if (!parms)
3422 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003423 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3424 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303425 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303426 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303427 struct listnode *node;
3428 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303429 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303430 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303431 } else if (strstr(snd_card_status, "ONLINE")) {
3432 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303433 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003434 //send dts hpx license if enabled
3435 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303436 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303437 }
3438
3439 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003440 status = voice_set_parameters(adev, parms);
3441 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003442 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003444 status = platform_set_parameters(adev->platform, parms);
3445 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003446 goto done;
3447
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003448 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3449 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003450 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3452 adev->bluetooth_nrec = true;
3453 else
3454 adev->bluetooth_nrec = false;
3455 }
3456
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003457 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3458 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3460 adev->screen_off = false;
3461 else
3462 adev->screen_off = true;
3463 }
3464
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003465 ret = str_parms_get_int(parms, "rotation", &val);
3466 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003467 bool reverse_speakers = false;
3468 switch(val) {
3469 // FIXME: note that the code below assumes that the speakers are in the correct placement
3470 // relative to the user when the device is rotated 90deg from its default rotation. This
3471 // assumption is device-specific, not platform-specific like this code.
3472 case 270:
3473 reverse_speakers = true;
3474 break;
3475 case 0:
3476 case 90:
3477 case 180:
3478 break;
3479 default:
3480 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003481 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003482 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003483 if (status == 0) {
3484 if (adev->speaker_lr_swap != reverse_speakers) {
3485 adev->speaker_lr_swap = reverse_speakers;
3486 // only update the selected device if there is active pcm playback
3487 struct audio_usecase *usecase;
3488 struct listnode *node;
3489 list_for_each(node, &adev->usecase_list) {
3490 usecase = node_to_item(node, struct audio_usecase, list);
3491 if (usecase->type == PCM_PLAYBACK) {
3492 select_devices(adev, usecase->id);
3493 break;
3494 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003495 }
3496 }
3497 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003498 }
3499
Mingming Yin514a8bc2014-07-29 15:22:21 -07003500 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3501 if (ret >= 0) {
3502 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3503 adev->bt_wb_speech_enabled = true;
3504 else
3505 adev->bt_wb_speech_enabled = false;
3506 }
3507
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003508 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3509 if (ret >= 0) {
3510 val = atoi(value);
3511 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3512 ALOGV("cache new edid");
3513 platform_cache_edid(adev->platform);
3514 }
3515 }
3516
3517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3518 if (ret >= 0) {
3519 val = atoi(value);
3520 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3521 ALOGV("invalidate cached edid");
3522 platform_invalidate_edid(adev->platform);
3523 }
3524 }
3525
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003526 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003527
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003528done:
3529 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003530 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303531error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003532 ALOGV("%s: exit with code(%d)", __func__, status);
3533 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534}
3535
3536static char* adev_get_parameters(const struct audio_hw_device *dev,
3537 const char *keys)
3538{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003539 struct audio_device *adev = (struct audio_device *)dev;
3540 struct str_parms *reply = str_parms_create();
3541 struct str_parms *query = str_parms_create_str(keys);
3542 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303543 char value[256] = {0};
3544 int ret = 0;
3545
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003546 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003547 if (reply) {
3548 str_parms_destroy(reply);
3549 }
3550 if (query) {
3551 str_parms_destroy(query);
3552 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003553 ALOGE("adev_get_parameters: failed to create query or reply");
3554 return NULL;
3555 }
3556
Naresh Tannirud7205b62014-06-20 02:54:48 +05303557 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3558 sizeof(value));
3559 if (ret >=0) {
3560 int val = 1;
3561 pthread_mutex_lock(&adev->snd_card_status.lock);
3562 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3563 val = 0;
3564 pthread_mutex_unlock(&adev->snd_card_status.lock);
3565 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3566 goto exit;
3567 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003568
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003569 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003570 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003571 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003572 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303573 pthread_mutex_unlock(&adev->lock);
3574
Naresh Tannirud7205b62014-06-20 02:54:48 +05303575exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003576 str = str_parms_to_str(reply);
3577 str_parms_destroy(query);
3578 str_parms_destroy(reply);
3579
3580 ALOGV("%s: exit: returns - %s", __func__, str);
3581 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582}
3583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003584static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585{
3586 return 0;
3587}
3588
3589static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3590{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003591 int ret;
3592 struct audio_device *adev = (struct audio_device *)dev;
3593 pthread_mutex_lock(&adev->lock);
3594 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003595 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003596 pthread_mutex_unlock(&adev->lock);
3597 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598}
3599
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003600static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3601 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602{
3603 return -ENOSYS;
3604}
3605
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003606static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3607 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608{
3609 return -ENOSYS;
3610}
3611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003612static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3613 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614{
3615 return -ENOSYS;
3616}
3617
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003618static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3619 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620{
3621 return -ENOSYS;
3622}
3623
3624static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3625{
3626 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 pthread_mutex_lock(&adev->lock);
3629 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003630 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003632 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003633 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003634 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003635 adev->current_call_output = NULL;
3636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 }
3638 pthread_mutex_unlock(&adev->lock);
3639 return 0;
3640}
3641
3642static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3643{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003644 int ret;
3645
3646 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003647 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003648 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3649 pthread_mutex_unlock(&adev->lock);
3650
3651 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652}
3653
3654static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3655{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003656 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 return 0;
3658}
3659
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003660static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 const struct audio_config *config)
3662{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003663 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003665 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3666 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667}
3668
3669static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003670 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 audio_devices_t devices,
3672 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003673 struct audio_stream_in **stream_in,
3674 audio_input_flags_t flags __unused,
3675 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003676 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677{
3678 struct audio_device *adev = (struct audio_device *)dev;
3679 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003680 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003681 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003682 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 *stream_in = NULL;
3685 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3686 return -EINVAL;
3687
3688 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003689
3690 if (!in) {
3691 ALOGE("failed to allocate input stream");
3692 return -ENOMEM;
3693 }
3694
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303695 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003696 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3697 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003699 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003700 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 in->stream.common.get_sample_rate = in_get_sample_rate;
3703 in->stream.common.set_sample_rate = in_set_sample_rate;
3704 in->stream.common.get_buffer_size = in_get_buffer_size;
3705 in->stream.common.get_channels = in_get_channels;
3706 in->stream.common.get_format = in_get_format;
3707 in->stream.common.set_format = in_set_format;
3708 in->stream.common.standby = in_standby;
3709 in->stream.common.dump = in_dump;
3710 in->stream.common.set_parameters = in_set_parameters;
3711 in->stream.common.get_parameters = in_get_parameters;
3712 in->stream.common.add_audio_effect = in_add_audio_effect;
3713 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3714 in->stream.set_gain = in_set_gain;
3715 in->stream.read = in_read;
3716 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3717
3718 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003719 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 in->standby = 1;
3722 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003723 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003724 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725
3726 /* Update config params with the requested sample rate and channels */
3727 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003728 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3729 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3730 is_low_latency = true;
3731#if LOW_LATENCY_CAPTURE_USE_CASE
3732 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3733#endif
3734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003737 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003739 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303740 if (adev->mode != AUDIO_MODE_IN_CALL) {
3741 ret = -EINVAL;
3742 goto err_open;
3743 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003744 if (config->sample_rate == 0)
3745 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3746 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3747 config->sample_rate != 8000) {
3748 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3749 ret = -EINVAL;
3750 goto err_open;
3751 }
3752 if (config->format == AUDIO_FORMAT_DEFAULT)
3753 config->format = AUDIO_FORMAT_PCM_16_BIT;
3754 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3755 config->format = AUDIO_FORMAT_PCM_16_BIT;
3756 ret = -EINVAL;
3757 goto err_open;
3758 }
3759
3760 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3761 in->config = pcm_config_afe_proxy_record;
3762 in->config.channels = channel_count;
3763 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303764 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3765 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003766 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003767 audio_extn_compr_cap_format_supported(config->format) &&
3768 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003769 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003770 } else {
3771 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003772 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003773 buffer_size = get_input_buffer_size(config->sample_rate,
3774 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003775 channel_count,
3776 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003777 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003778 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3779 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3780 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3781 (in->config.rate == 8000 || in->config.rate == 16000) &&
3782 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3783 voice_extn_compress_voip_open_input_stream(in);
3784 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003785 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003787 /* This stream could be for sound trigger lab,
3788 get sound trigger pcm if present */
3789 audio_extn_sound_trigger_check_and_get_session(in);
3790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003792 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003793 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794
3795err_open:
3796 free(in);
3797 *stream_in = NULL;
3798 return ret;
3799}
3800
3801static void adev_close_input_stream(struct audio_hw_device *dev,
3802 struct audio_stream_in *stream)
3803{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003804 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003805 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003806 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303807
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303808 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003809
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303810 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003811 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303812
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003813 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303814 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003815 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303816 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003817 if (ret != 0)
3818 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3819 __func__, ret);
3820 } else
3821 in_standby(&stream->common);
3822
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003823 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003824 audio_extn_ssr_deinit();
3825 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826
Mingming Yine62d7842013-10-25 16:26:03 -07003827 if(audio_extn_compr_cap_enabled() &&
3828 audio_extn_compr_cap_format_supported(in->config.format))
3829 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003830
3831 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 return;
3833}
3834
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003835static int adev_dump(const audio_hw_device_t *device __unused,
3836 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837{
3838 return 0;
3839}
3840
3841static int adev_close(hw_device_t *device)
3842{
3843 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003844
3845 if (!adev)
3846 return 0;
3847
3848 pthread_mutex_lock(&adev_init_lock);
3849
3850 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003851 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003852 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003853 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003854 audio_route_free(adev->audio_route);
3855 free(adev->snd_dev_ref_cnt);
3856 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003857 if (adev->adm_deinit)
3858 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003859 free(device);
3860 adev = NULL;
3861 }
3862 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 return 0;
3865}
3866
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003867/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3868 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3869 * just that it _might_ work.
3870 */
3871static int period_size_is_plausible_for_low_latency(int period_size)
3872{
3873 switch (period_size) {
3874 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003875 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003876 case 240:
3877 case 320:
3878 case 480:
3879 return 1;
3880 default:
3881 return 0;
3882 }
3883}
3884
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885static int adev_open(const hw_module_t *module, const char *name,
3886 hw_device_t **device)
3887{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003888 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003890 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3892
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003893 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003894 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003895 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003896 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003897 ALOGD("%s: returning existing instance of adev", __func__);
3898 ALOGD("%s: exit", __func__);
3899 pthread_mutex_unlock(&adev_init_lock);
3900 return 0;
3901 }
3902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 adev = calloc(1, sizeof(struct audio_device));
3904
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003905 if (!adev) {
3906 pthread_mutex_unlock(&adev_init_lock);
3907 return -ENOMEM;
3908 }
3909
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003910 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3913 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3914 adev->device.common.module = (struct hw_module_t *)module;
3915 adev->device.common.close = adev_close;
3916
3917 adev->device.init_check = adev_init_check;
3918 adev->device.set_voice_volume = adev_set_voice_volume;
3919 adev->device.set_master_volume = adev_set_master_volume;
3920 adev->device.get_master_volume = adev_get_master_volume;
3921 adev->device.set_master_mute = adev_set_master_mute;
3922 adev->device.get_master_mute = adev_get_master_mute;
3923 adev->device.set_mode = adev_set_mode;
3924 adev->device.set_mic_mute = adev_set_mic_mute;
3925 adev->device.get_mic_mute = adev_get_mic_mute;
3926 adev->device.set_parameters = adev_set_parameters;
3927 adev->device.get_parameters = adev_get_parameters;
3928 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3929 adev->device.open_output_stream = adev_open_output_stream;
3930 adev->device.close_output_stream = adev_close_output_stream;
3931 adev->device.open_input_stream = adev_open_input_stream;
3932 adev->device.close_input_stream = adev_close_input_stream;
3933 adev->device.dump = adev_dump;
3934
3935 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003937 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003938 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003941 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003942 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003943 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003944 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003945 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003946 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003947 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303948 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303949 adev->perf_lock_opts[0] = 0x101;
3950 adev->perf_lock_opts[1] = 0x20E;
3951 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303952
3953 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3954 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003955 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003956 adev->platform = platform_init(adev);
3957 if (!adev->platform) {
3958 free(adev->snd_dev_ref_cnt);
3959 free(adev);
3960 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3961 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003962 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003963 return -EINVAL;
3964 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003965
Naresh Tanniru4c630392014-05-12 01:05:52 +05303966 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3967
Eric Laurentc4aef752013-09-12 17:45:53 -07003968 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3969 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3970 if (adev->visualizer_lib == NULL) {
3971 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3972 } else {
3973 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3974 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003975 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003976 "visualizer_hal_start_output");
3977 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003978 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003979 "visualizer_hal_stop_output");
3980 }
3981 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003982 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003983 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003984
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003985 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3986 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3987 if (adev->offload_effects_lib == NULL) {
3988 ALOGE("%s: DLOPEN failed for %s", __func__,
3989 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3990 } else {
3991 ALOGV("%s: DLOPEN successful for %s", __func__,
3992 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3993 adev->offload_effects_start_output =
3994 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3995 "offload_effects_bundle_hal_start_output");
3996 adev->offload_effects_stop_output =
3997 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3998 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003999 adev->offload_effects_set_hpx_state =
4000 (int (*)(bool))dlsym(adev->offload_effects_lib,
4001 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304002 adev->offload_effects_get_parameters =
4003 (void (*)(struct str_parms *, struct str_parms *))
4004 dlsym(adev->offload_effects_lib,
4005 "offload_effects_bundle_get_parameters");
4006 adev->offload_effects_set_parameters =
4007 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4008 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004009 }
4010 }
4011
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004012 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4013 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4014 if (adev->adm_lib == NULL) {
4015 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4016 } else {
4017 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4018 adev->adm_init = (adm_init_t)
4019 dlsym(adev->adm_lib, "adm_init");
4020 adev->adm_deinit = (adm_deinit_t)
4021 dlsym(adev->adm_lib, "adm_deinit");
4022 adev->adm_register_input_stream = (adm_register_input_stream_t)
4023 dlsym(adev->adm_lib, "adm_register_input_stream");
4024 adev->adm_register_output_stream = (adm_register_output_stream_t)
4025 dlsym(adev->adm_lib, "adm_register_output_stream");
4026 adev->adm_deregister_stream = (adm_deregister_stream_t)
4027 dlsym(adev->adm_lib, "adm_deregister_stream");
4028 adev->adm_request_focus = (adm_request_focus_t)
4029 dlsym(adev->adm_lib, "adm_request_focus");
4030 adev->adm_abandon_focus = (adm_abandon_focus_t)
4031 dlsym(adev->adm_lib, "adm_abandon_focus");
4032 }
4033 }
4034
Mingming Yin514a8bc2014-07-29 15:22:21 -07004035 adev->bt_wb_speech_enabled = false;
4036
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004037 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038 *device = &adev->device.common;
4039
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004040 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4041 &adev->streams_output_cfg_list);
4042
Kiran Kandi910e1862013-10-29 13:29:42 -07004043 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004044
4045 char value[PROPERTY_VALUE_MAX];
4046 int trial;
4047 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4048 trial = atoi(value);
4049 if (period_size_is_plausible_for_low_latency(trial)) {
4050 pcm_config_low_latency.period_size = trial;
4051 pcm_config_low_latency.start_threshold = trial / 4;
4052 pcm_config_low_latency.avail_min = trial / 4;
4053 configured_low_latency_capture_period_size = trial;
4054 }
4055 }
4056 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4057 trial = atoi(value);
4058 if (period_size_is_plausible_for_low_latency(trial)) {
4059 configured_low_latency_capture_period_size = trial;
4060 }
4061 }
4062
vivek mehta446c3962015-09-14 10:57:35 -07004063 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004064 pthread_mutex_unlock(&adev_init_lock);
4065
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004066 if (adev->adm_init)
4067 adev->adm_data = adev->adm_init();
4068
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304069 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004070 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071 return 0;
4072}
4073
4074static struct hw_module_methods_t hal_module_methods = {
4075 .open = adev_open,
4076};
4077
4078struct audio_module HAL_MODULE_INFO_SYM = {
4079 .common = {
4080 .tag = HARDWARE_MODULE_TAG,
4081 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4082 .hal_api_version = HARDWARE_HAL_API_VERSION,
4083 .id = AUDIO_HARDWARE_MODULE_ID,
4084 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004085 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086 .methods = &hal_module_methods,
4087 },
4088};