blob: 8c729ff75475902e48b1ba2afa46fbbf10ad722d [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 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700962 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
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);
2151 char *str;
2152 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) {
2159 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2160 return NULL;
2161 }
2162
Eric Laurent994a6932013-07-17 11:51:42 -07002163 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2165 if (ret >= 0) {
2166 value[0] = '\0';
2167 i = 0;
2168 while (out->supported_channel_masks[i] != 0) {
2169 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2170 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2171 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002172 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002174 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 first = false;
2176 break;
2177 }
2178 }
2179 i++;
2180 }
2181 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2182 str = str_parms_to_str(reply);
2183 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002184 voice_extn_out_get_parameters(out, query, reply);
2185 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002186 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002187 free(str);
2188 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002191
Alexy Joseph62142aa2015-11-16 15:10:34 -08002192
2193 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2194 if (ret >= 0) {
2195 value[0] = '\0';
2196 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2197 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302198 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002199 } else {
2200 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302201 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002202 }
2203 str_parms_add_str(reply, "is_direct_pcm_track", value);
2204 str = str_parms_to_str(reply);
2205 }
2206
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002207 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2208 if (ret >= 0) {
2209 value[0] = '\0';
2210 i = 0;
2211 first = true;
2212 while (out->supported_formats[i] != 0) {
2213 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2214 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2215 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002216 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002217 }
2218 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2219 first = false;
2220 break;
2221 }
2222 }
2223 i++;
2224 }
2225 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2226 str = str_parms_to_str(reply);
2227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 str_parms_destroy(query);
2229 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002230 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 return str;
2232}
2233
2234static uint32_t out_get_latency(const struct audio_stream_out *stream)
2235{
2236 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002237 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238
Alexy Josephaa54c872014-12-03 02:46:47 -08002239 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002240 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002241 } else {
2242 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002243 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002244 }
2245
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302246 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002247 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248}
2249
2250static int out_set_volume(struct audio_stream_out *stream, float left,
2251 float right)
2252{
Eric Laurenta9024de2013-04-04 09:19:12 -07002253 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002254 int volume[2];
2255
Eric Laurenta9024de2013-04-04 09:19:12 -07002256 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2257 /* only take left channel into account: the API is for stereo anyway */
2258 out->muted = (left == 0.0f);
2259 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002260 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002261 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2262 /*
2263 * Set mute or umute on HDMI passthrough stream.
2264 * Only take left channel into account.
2265 * Mute is 0 and unmute 1
2266 */
2267 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2268 } else {
2269 char mixer_ctl_name[128];
2270 struct audio_device *adev = out->dev;
2271 struct mixer_ctl *ctl;
2272 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002273 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002274
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002275 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2276 "Compress Playback %d Volume", pcm_device_id);
2277 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2278 if (!ctl) {
2279 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2280 __func__, mixer_ctl_name);
2281 return -EINVAL;
2282 }
2283 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2284 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2285 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2286 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002288 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 return -ENOSYS;
2291}
2292
2293static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2294 size_t bytes)
2295{
2296 struct stream_out *out = (struct stream_out *)stream;
2297 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302298 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002299 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002301 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302302
Naresh Tanniru80659832014-06-04 18:17:56 +05302303 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002304 // increase written size during SSR to avoid mismatch
2305 // with the written frames count in AF
2306 if (!is_offload_usecase(out->usecase))
2307 out->written += bytes / (out->config.channels * sizeof(short));
2308
Naresh Tanniru80659832014-06-04 18:17:56 +05302309 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302310 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302311 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302312 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002313 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302314 //during SSR for compress usecase we should return error to flinger
2315 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2316 pthread_mutex_unlock(&out->lock);
2317 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302318 }
2319 }
2320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002322 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002323 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002324 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2325 ret = voice_extn_compress_voip_start_output_stream(out);
2326 else
2327 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002328 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002331 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 goto exit;
2333 }
vivek mehta446c3962015-09-14 10:57:35 -07002334 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002335 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337
Ashish Jain81eb2a82015-05-13 10:52:34 +05302338 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2339 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2340 adev->is_channel_status_set = true;
2341 }
2342
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002343 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002344 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002345 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002346 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002347 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2348 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302349 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2350 ALOGD("copl(%p):send next track params in gapless", out);
2351 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2352 out->send_next_track_params = false;
2353 out->is_compr_metadata_avail = false;
2354 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002355 }
2356
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302358 if (ret < 0)
2359 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002360 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002361 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302362 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302364 } else if (-ENETRESET == ret) {
2365 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2366 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2367 pthread_mutex_unlock(&out->lock);
2368 out_standby(&out->stream.common);
2369 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302371 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002373 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 out->playback_started = 1;
2375 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002376
2377 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2378 popcount(out->channel_mask),
2379 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 }
2381 pthread_mutex_unlock(&out->lock);
2382 return ret;
2383 } else {
2384 if (out->pcm) {
2385 if (out->muted)
2386 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002389
2390 if (adev->adm_request_focus)
2391 adev->adm_request_focus(adev->adm_data, out->handle);
2392
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002393 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2394 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2395 else
2396 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002397
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302398 if (ret < 0)
2399 ret = -errno;
2400 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002401 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002402
2403 if (adev->adm_abandon_focus)
2404 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406 }
2407
2408exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302409 /* ToDo: There may be a corner case when SSR happens back to back during
2410 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302411 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302412 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302413 }
2414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 pthread_mutex_unlock(&out->lock);
2416
2417 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002418 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002419 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302420 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302421 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302422 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302423 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302424 out->standby = true;
2425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002427 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302428 out_get_sample_rate(&out->stream.common));
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 }
2431 return bytes;
2432}
2433
2434static int out_get_render_position(const struct audio_stream_out *stream,
2435 uint32_t *dsp_frames)
2436{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302438 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002439
2440 if (dsp_frames == NULL)
2441 return -EINVAL;
2442
2443 *dsp_frames = 0;
2444 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002445 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002446 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302448 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302450 if (ret < 0)
2451 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 ALOGVV("%s rendered frames %d sample_rate %d",
2453 __func__, *dsp_frames, out->sample_rate);
2454 }
2455 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302456 if (-ENETRESET == ret) {
2457 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2458 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2459 return -EINVAL;
2460 } else if(ret < 0) {
2461 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2462 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302463 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2464 /*
2465 * Handle corner case where compress session is closed during SSR
2466 * and timestamp is queried
2467 */
2468 ALOGE(" ERROR: sound card not active, return error");
2469 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302470 } else {
2471 return 0;
2472 }
Zhou Song32a556e2015-05-05 10:46:56 +08002473 } else if (audio_is_linear_pcm(out->format)) {
2474 *dsp_frames = out->written;
2475 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002476 } else
2477 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478}
2479
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002480static int out_add_audio_effect(const struct audio_stream *stream __unused,
2481 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482{
2483 return 0;
2484}
2485
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002486static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2487 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488{
2489 return 0;
2490}
2491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002492static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2493 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494{
2495 return -EINVAL;
2496}
2497
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002498static int out_get_presentation_position(const struct audio_stream_out *stream,
2499 uint64_t *frames, struct timespec *timestamp)
2500{
2501 struct stream_out *out = (struct stream_out *)stream;
2502 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002503 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002504
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002505 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002506
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002507 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002508 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302509 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002510 &out->sample_rate);
2511 ALOGVV("%s rendered frames %ld sample_rate %d",
2512 __func__, dsp_frames, out->sample_rate);
2513 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302514 if (ret < 0)
2515 ret = -errno;
2516 if (-ENETRESET == ret) {
2517 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2518 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2519 ret = -EINVAL;
2520 } else
2521 ret = 0;
2522
Eric Laurent949a0892013-09-20 09:20:13 -07002523 /* this is the best we can do */
2524 clock_gettime(CLOCK_MONOTONIC, timestamp);
2525 }
2526 } else {
2527 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002528 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002529 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2530 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002531 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002532 // This adjustment accounts for buffering after app processor.
2533 // It is based on estimated DSP latency per use case, rather than exact.
2534 signed_frames -=
2535 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2536
Eric Laurent949a0892013-09-20 09:20:13 -07002537 // It would be unusual for this value to be negative, but check just in case ...
2538 if (signed_frames >= 0) {
2539 *frames = signed_frames;
2540 ret = 0;
2541 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002542 }
2543 }
2544 }
2545
2546 pthread_mutex_unlock(&out->lock);
2547
2548 return ret;
2549}
2550
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002551static int out_set_callback(struct audio_stream_out *stream,
2552 stream_callback_t callback, void *cookie)
2553{
2554 struct stream_out *out = (struct stream_out *)stream;
2555
2556 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002557 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002558 out->offload_callback = callback;
2559 out->offload_cookie = cookie;
2560 pthread_mutex_unlock(&out->lock);
2561 return 0;
2562}
2563
2564static int out_pause(struct audio_stream_out* stream)
2565{
2566 struct stream_out *out = (struct stream_out *)stream;
2567 int status = -ENOSYS;
2568 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002569 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002570 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002571 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302573 struct audio_device *adev = out->dev;
2574 int snd_scard_state = get_snd_card_state(adev);
2575
2576 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2577 status = compress_pause(out->compr);
2578
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002579 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002580
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302581 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002582 audio_extn_dts_notify_playback_state(out->usecase, 0,
2583 out->sample_rate, popcount(out->channel_mask),
2584 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002585 }
2586 pthread_mutex_unlock(&out->lock);
2587 }
2588 return status;
2589}
2590
2591static int out_resume(struct audio_stream_out* stream)
2592{
2593 struct stream_out *out = (struct stream_out *)stream;
2594 int status = -ENOSYS;
2595 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002596 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002597 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002599 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002600 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302601 struct audio_device *adev = out->dev;
2602 int snd_scard_state = get_snd_card_state(adev);
2603
2604 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2605 status = compress_resume(out->compr);
2606
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002608
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302609 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002610 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2611 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002612 }
2613 pthread_mutex_unlock(&out->lock);
2614 }
2615 return status;
2616}
2617
2618static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2619{
2620 struct stream_out *out = (struct stream_out *)stream;
2621 int status = -ENOSYS;
2622 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002623 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002624 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2626 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2627 else
2628 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2629 pthread_mutex_unlock(&out->lock);
2630 }
2631 return status;
2632}
2633
2634static int out_flush(struct audio_stream_out* stream)
2635{
2636 struct stream_out *out = (struct stream_out *)stream;
2637 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002638 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002639 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002640 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002641 stop_compressed_output_l(out);
2642 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002643 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002644 return 0;
2645 }
2646 return -ENOSYS;
2647}
2648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649/** audio_stream_in implementation **/
2650static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2651{
2652 struct stream_in *in = (struct stream_in *)stream;
2653
2654 return in->config.rate;
2655}
2656
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002657static int in_set_sample_rate(struct audio_stream *stream __unused,
2658 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659{
2660 return -ENOSYS;
2661}
2662
2663static size_t in_get_buffer_size(const struct audio_stream *stream)
2664{
2665 struct stream_in *in = (struct stream_in *)stream;
2666
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002667 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2668 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002669 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2670 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002671
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002672 return in->config.period_size *
2673 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674}
2675
2676static uint32_t in_get_channels(const struct audio_stream *stream)
2677{
2678 struct stream_in *in = (struct stream_in *)stream;
2679
2680 return in->channel_mask;
2681}
2682
2683static audio_format_t in_get_format(const struct audio_stream *stream)
2684{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002685 struct stream_in *in = (struct stream_in *)stream;
2686
2687 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688}
2689
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002690static int in_set_format(struct audio_stream *stream __unused,
2691 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692{
2693 return -ENOSYS;
2694}
2695
2696static int in_standby(struct audio_stream *stream)
2697{
2698 struct stream_in *in = (struct stream_in *)stream;
2699 struct audio_device *adev = in->dev;
2700 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302701 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2702 stream, in->usecase, use_case_table[in->usecase]);
2703
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002704 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2705 /* Ignore standby in case of voip call because the voip input
2706 * stream is closed in adev_close_input_stream()
2707 */
2708 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2709 return status;
2710 }
2711
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002712 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002713 if (!in->standby && in->is_st_session) {
2714 ALOGD("%s: sound trigger pcm stop lab", __func__);
2715 audio_extn_sound_trigger_stop_lab(in);
2716 in->standby = 1;
2717 }
2718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002720 if (adev->adm_deregister_stream)
2721 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2722
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002723 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002725 if (in->pcm) {
2726 pcm_close(in->pcm);
2727 in->pcm = NULL;
2728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002730 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 }
2732 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002733 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 return status;
2735}
2736
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002737static int in_dump(const struct audio_stream *stream __unused,
2738 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739{
2740 return 0;
2741}
2742
2743static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2744{
2745 struct stream_in *in = (struct stream_in *)stream;
2746 struct audio_device *adev = in->dev;
2747 struct str_parms *parms;
2748 char *str;
2749 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002750 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302752 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753 parms = str_parms_create_str(kvpairs);
2754
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302755 if (!parms)
2756 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002757 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002758 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002759
2760 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2761 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 val = atoi(value);
2763 /* no audio source uses val == 0 */
2764 if ((in->source != val) && (val != 0)) {
2765 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002766 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2767 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2768 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2769 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002770 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002771 err = voice_extn_compress_voip_open_input_stream(in);
2772 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002773 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002774 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002775 }
2776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 }
2778 }
2779
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002780 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2781 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002783 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 in->device = val;
2785 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002786 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002787 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 }
2789 }
2790
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002791done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002793 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794
2795 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302796error:
Eric Laurent994a6932013-07-17 11:51:42 -07002797 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 return ret;
2799}
2800
2801static char* in_get_parameters(const struct audio_stream *stream,
2802 const char *keys)
2803{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002804 struct stream_in *in = (struct stream_in *)stream;
2805 struct str_parms *query = str_parms_create_str(keys);
2806 char *str;
2807 char value[256];
2808 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002809
2810 if (!query || !reply) {
2811 ALOGE("in_get_parameters: failed to create query or reply");
2812 return NULL;
2813 }
2814
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002815 ALOGV("%s: enter: keys - %s", __func__, keys);
2816
2817 voice_extn_in_get_parameters(in, query, reply);
2818
2819 str = str_parms_to_str(reply);
2820 str_parms_destroy(query);
2821 str_parms_destroy(reply);
2822
2823 ALOGV("%s: exit: returns - %s", __func__, str);
2824 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825}
2826
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002827static int in_set_gain(struct audio_stream_in *stream __unused,
2828 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829{
2830 return 0;
2831}
2832
2833static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2834 size_t bytes)
2835{
2836 struct stream_in *in = (struct stream_in *)stream;
2837 struct audio_device *adev = in->dev;
2838 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302839 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002841 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302842
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002843 if (in->is_st_session) {
2844 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2845 /* Read from sound trigger HAL */
2846 audio_extn_sound_trigger_read(in, buffer, bytes);
2847 pthread_mutex_unlock(&in->lock);
2848 return bytes;
2849 }
2850
2851 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2852 ALOGD(" %s: sound card is not active/SSR state", __func__);
2853 ret= -EIO;;
2854 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302855 }
2856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002858 pthread_mutex_lock(&adev->lock);
2859 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2860 ret = voice_extn_compress_voip_start_input_stream(in);
2861 else
2862 ret = start_input_stream(in);
2863 pthread_mutex_unlock(&adev->lock);
2864 if (ret != 0) {
2865 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866 }
2867 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002868 if (adev->adm_register_input_stream)
2869 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002872 if (adev->adm_request_focus)
2873 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002876 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002877 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002878 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2879 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002880 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2881 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002882 else
2883 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302884 if (ret < 0)
2885 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 }
2887
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002888 if (adev->adm_abandon_focus)
2889 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 /*
2892 * Instead of writing zeroes here, we could trust the hardware
2893 * to always provide zeroes when muted.
2894 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302895 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2896 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 memset(buffer, 0, bytes);
2898
2899exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302900 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302901 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002902 if (-ENETRESET == ret)
2903 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 pthread_mutex_unlock(&in->lock);
2906
2907 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302908 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302909 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302910 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302911 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302912 in->standby = true;
2913 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302914 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002916 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002917 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302918 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 }
2920 return bytes;
2921}
2922
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002923static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924{
2925 return 0;
2926}
2927
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002928static int add_remove_audio_effect(const struct audio_stream *stream,
2929 effect_handle_t effect,
2930 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002932 struct stream_in *in = (struct stream_in *)stream;
2933 int status = 0;
2934 effect_descriptor_t desc;
2935
2936 status = (*effect)->get_descriptor(effect, &desc);
2937 if (status != 0)
2938 return status;
2939
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002940 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002941 pthread_mutex_lock(&in->dev->lock);
2942 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2943 in->enable_aec != enable &&
2944 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2945 in->enable_aec = enable;
2946 if (!in->standby)
2947 select_devices(in->dev, in->usecase);
2948 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002949 if (in->enable_ns != enable &&
2950 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2951 in->enable_ns = enable;
2952 if (!in->standby)
2953 select_devices(in->dev, in->usecase);
2954 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002955 pthread_mutex_unlock(&in->dev->lock);
2956 pthread_mutex_unlock(&in->lock);
2957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958 return 0;
2959}
2960
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002961static int in_add_audio_effect(const struct audio_stream *stream,
2962 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963{
Eric Laurent994a6932013-07-17 11:51:42 -07002964 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002965 return add_remove_audio_effect(stream, effect, true);
2966}
2967
2968static int in_remove_audio_effect(const struct audio_stream *stream,
2969 effect_handle_t effect)
2970{
Eric Laurent994a6932013-07-17 11:51:42 -07002971 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002972 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973}
2974
2975static int adev_open_output_stream(struct audio_hw_device *dev,
2976 audio_io_handle_t handle,
2977 audio_devices_t devices,
2978 audio_output_flags_t flags,
2979 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002980 struct audio_stream_out **stream_out,
2981 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982{
2983 struct audio_device *adev = (struct audio_device *)dev;
2984 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002985 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002986 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302989
2990 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2991 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002992 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302993 return -EINVAL;
2994 }
2995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2997
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302998 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2999 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3000 devices, flags, &out->stream);
3001
3002
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003003 if (!out) {
3004 return -ENOMEM;
3005 }
3006
Haynes Mathew George204045b2015-02-25 20:32:03 -08003007 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003008 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003009 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 if (devices == AUDIO_DEVICE_NONE)
3012 devices = AUDIO_DEVICE_OUT_SPEAKER;
3013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 out->flags = flags;
3015 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003016 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003017 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018 out->sample_rate = config->sample_rate;
3019 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3020 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003021 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003022 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003023 out->non_blocking = 0;
3024 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025
3026 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003027 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
3028 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003029 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3030 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3031
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003032 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003033 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3034 ret = read_hdmi_channel_masks(out);
3035
3036 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3037 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003038 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003039 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003040 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003041
3042 if (config->sample_rate == 0)
3043 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3044 if (config->channel_mask == 0)
3045 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3046
3047 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3050 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003052 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003054 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3055 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003056 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057 ret = voice_extn_compress_voip_open_output_stream(out);
3058 if (ret != 0) {
3059 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3060 __func__, ret);
3061 goto error_open;
3062 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003063 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3064 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3067 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3068 ALOGE("%s: Unsupported Offload information", __func__);
3069 ret = -EINVAL;
3070 goto error_open;
3071 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003072
3073 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3074 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3075 ALOGV("read and update_pass through formats");
3076 ret = audio_extn_dolby_update_passt_formats(adev, out);
3077 if(ret != 0) {
3078 goto error_open;
3079 }
3080 if(config->offload_info.format == 0)
3081 config->offload_info.format = out->supported_formats[0];
3082 }
3083
Mingming Yin90310102013-11-13 16:57:00 -08003084 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003085 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003086 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 ret = -EINVAL;
3088 goto error_open;
3089 }
3090
3091 out->compr_config.codec = (struct snd_codec *)
3092 calloc(1, sizeof(struct snd_codec));
3093
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003094 if (!out->compr_config.codec) {
3095 ret = -ENOMEM;
3096 goto error_open;
3097 }
3098
vivek mehta0ea887a2015-08-26 14:01:20 -07003099 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003100 out->usecase = get_offload_usecase(adev, true);
3101 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003102 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003103 out->stream.set_callback = out_set_callback;
3104 out->stream.pause = out_pause;
3105 out->stream.resume = out_resume;
3106 out->stream.drain = out_drain;
3107 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003108 out->usecase = get_offload_usecase(adev, false);
3109 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003110 }
vivek mehta446c3962015-09-14 10:57:35 -07003111
3112 if (out->usecase == USECASE_INVALID) {
3113 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3114 ret = -EEXIST;
3115 goto error_open;
3116 }
3117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 if (config->offload_info.channel_mask)
3119 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003120 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003122 config->offload_info.channel_mask = config->channel_mask;
3123 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003124 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003125 out->sample_rate = config->offload_info.sample_rate;
3126
Mingming Yin3ee55c62014-08-04 14:23:35 -07003127 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003129 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003130 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003131 audio_extn_dolby_get_snd_codec_id(adev, out,
3132 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003133 else
3134 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003136
3137 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3138 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003139 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003140 platform_get_pcm_offload_buffer_size(&config->offload_info);
3141 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3142 out->compr_config.fragment_size =
3143 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003144 } else {
3145 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003146 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003147 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3149 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003150 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151 out->compr_config.codec->bit_rate =
3152 config->offload_info.bit_rate;
3153 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003154 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003155 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303156 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003157 /*TODO: Do we need to change it for passthrough */
3158 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159
Manish Dewangana6fc5442015-08-24 20:30:31 +05303160 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3161 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3162 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3163 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003164 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3165 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003166 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003167 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003168 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3169 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003170
Mingming Yin3ee55c62014-08-04 14:23:35 -07003171 if (out->bit_width == 24) {
3172 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3173 }
3174
Amit Shekhar6f461b12014-08-01 14:52:58 -07003175 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303176 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003177
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3179 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003180
Mingming Yin497419f2015-07-01 16:57:32 -07003181 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003182 //this flag is set from framework only if its for PCM formats
3183 //no need to check for PCM format again
3184 out->non_blocking = 0;
3185 out->use_small_bufs = true;
3186 ALOGI("Keep write blocking for small buff: non_blockling %d",
3187 out->non_blocking);
3188 }
3189
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003190 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303191 out->send_next_track_params = false;
3192 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003193 out->offload_state = OFFLOAD_STATE_IDLE;
3194 out->playback_started = 0;
3195
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003196 audio_extn_dts_create_state_notifier_node(out->usecase);
3197
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198 create_offload_callback_thread(out);
3199 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3200 __func__, config->offload_info.version,
3201 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003202 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003203 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003204 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3205 ret = voice_check_and_set_incall_music_usecase(adev, out);
3206 if (ret != 0) {
3207 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3208 __func__, ret);
3209 goto error_open;
3210 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003211 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3212 if (config->sample_rate == 0)
3213 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3214 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3215 config->sample_rate != 8000) {
3216 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3217 ret = -EINVAL;
3218 goto error_open;
3219 }
3220 out->sample_rate = config->sample_rate;
3221 out->config.rate = config->sample_rate;
3222 if (config->format == AUDIO_FORMAT_DEFAULT)
3223 config->format = AUDIO_FORMAT_PCM_16_BIT;
3224 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3225 config->format = AUDIO_FORMAT_PCM_16_BIT;
3226 ret = -EINVAL;
3227 goto error_open;
3228 }
3229 out->format = config->format;
3230 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3231 out->config = pcm_config_afe_proxy_playback;
3232 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003233 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3234 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3235 out->config = pcm_config_low_latency;
3236 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003237 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003238 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3240 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003241 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003242 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3243 format = AUDIO_FORMAT_PCM_16_BIT;
3244 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3245 out->config = pcm_config_deep_buffer;
3246 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003247 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003248 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003249 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003250 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003251 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003252 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 }
3254
Amit Shekhar1d896042014-10-03 13:16:09 -07003255 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3256 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003257 /* TODO remove this hardcoding and check why width is zero*/
3258 if (out->bit_width == 0)
3259 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003260 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3261 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003262 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303263 out->bit_width, out->channel_mask,
3264 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003265 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3266 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3267 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003268 if(adev->primary_output == NULL)
3269 adev->primary_output = out;
3270 else {
3271 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003272 ret = -EEXIST;
3273 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003274 }
3275 }
3276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 /* Check if this usecase is already existing */
3278 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003279 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3280 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003283 ret = -EEXIST;
3284 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 }
3286 pthread_mutex_unlock(&adev->lock);
3287
3288 out->stream.common.get_sample_rate = out_get_sample_rate;
3289 out->stream.common.set_sample_rate = out_set_sample_rate;
3290 out->stream.common.get_buffer_size = out_get_buffer_size;
3291 out->stream.common.get_channels = out_get_channels;
3292 out->stream.common.get_format = out_get_format;
3293 out->stream.common.set_format = out_set_format;
3294 out->stream.common.standby = out_standby;
3295 out->stream.common.dump = out_dump;
3296 out->stream.common.set_parameters = out_set_parameters;
3297 out->stream.common.get_parameters = out_get_parameters;
3298 out->stream.common.add_audio_effect = out_add_audio_effect;
3299 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3300 out->stream.get_latency = out_get_latency;
3301 out->stream.set_volume = out_set_volume;
3302 out->stream.write = out_write;
3303 out->stream.get_render_position = out_get_render_position;
3304 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003305 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003308 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003309 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310
3311 config->format = out->stream.common.get_format(&out->stream.common);
3312 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3313 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3314
3315 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303316 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003317 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003318
3319 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3320 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3321 popcount(out->channel_mask), out->playback_started);
3322
Eric Laurent994a6932013-07-17 11:51:42 -07003323 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003325
3326error_open:
3327 free(out);
3328 *stream_out = NULL;
3329 ALOGD("%s: exit: ret %d", __func__, ret);
3330 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003333static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334 struct audio_stream_out *stream)
3335{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003336 struct stream_out *out = (struct stream_out *)stream;
3337 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003338 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003339
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303340 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3341
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003342 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303343 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003344 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303345 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003346 if(ret != 0)
3347 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3348 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003349 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003350 out_standby(&stream->common);
3351
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003352 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003353 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003355 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 if (out->compr_config.codec != NULL)
3357 free(out->compr_config.codec);
3358 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003359
3360 if (adev->voice_tx_output == out)
3361 adev->voice_tx_output = NULL;
3362
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003363 pthread_cond_destroy(&out->cond);
3364 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003366 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367}
3368
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003369static void close_compress_sessions(struct audio_device *adev)
3370{
Mingming Yin7b762e72015-03-04 13:47:32 -08003371 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303372 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003373 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003374 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303375
3376 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003377 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303378 if (is_offload_usecase(usecase->id)) {
3379 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003380 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3381 out = usecase->stream.out;
3382 pthread_mutex_unlock(&adev->lock);
3383 out_standby(&out->stream.common);
3384 pthread_mutex_lock(&adev->lock);
3385 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303386 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003387 }
3388 pthread_mutex_unlock(&adev->lock);
3389}
3390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3392{
3393 struct audio_device *adev = (struct audio_device *)dev;
3394 struct str_parms *parms;
3395 char *str;
3396 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003397 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003398 int ret;
3399 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003401 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303404 if (!parms)
3405 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003406 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3407 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303408 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303409 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303410 struct listnode *node;
3411 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303412 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303413 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303414 } else if (strstr(snd_card_status, "ONLINE")) {
3415 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303416 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003417 //send dts hpx license if enabled
3418 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303419 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303420 }
3421
3422 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003423 status = voice_set_parameters(adev, parms);
3424 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003425 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003427 status = platform_set_parameters(adev->platform, parms);
3428 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003429 goto done;
3430
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003431 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3432 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003433 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3435 adev->bluetooth_nrec = true;
3436 else
3437 adev->bluetooth_nrec = false;
3438 }
3439
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003440 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3441 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3443 adev->screen_off = false;
3444 else
3445 adev->screen_off = true;
3446 }
3447
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003448 ret = str_parms_get_int(parms, "rotation", &val);
3449 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003450 bool reverse_speakers = false;
3451 switch(val) {
3452 // FIXME: note that the code below assumes that the speakers are in the correct placement
3453 // relative to the user when the device is rotated 90deg from its default rotation. This
3454 // assumption is device-specific, not platform-specific like this code.
3455 case 270:
3456 reverse_speakers = true;
3457 break;
3458 case 0:
3459 case 90:
3460 case 180:
3461 break;
3462 default:
3463 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003464 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003465 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003466 if (status == 0) {
3467 if (adev->speaker_lr_swap != reverse_speakers) {
3468 adev->speaker_lr_swap = reverse_speakers;
3469 // only update the selected device if there is active pcm playback
3470 struct audio_usecase *usecase;
3471 struct listnode *node;
3472 list_for_each(node, &adev->usecase_list) {
3473 usecase = node_to_item(node, struct audio_usecase, list);
3474 if (usecase->type == PCM_PLAYBACK) {
3475 select_devices(adev, usecase->id);
3476 break;
3477 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003478 }
3479 }
3480 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003481 }
3482
Mingming Yin514a8bc2014-07-29 15:22:21 -07003483 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3484 if (ret >= 0) {
3485 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3486 adev->bt_wb_speech_enabled = true;
3487 else
3488 adev->bt_wb_speech_enabled = false;
3489 }
3490
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003491 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3492 if (ret >= 0) {
3493 val = atoi(value);
3494 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3495 ALOGV("cache new edid");
3496 platform_cache_edid(adev->platform);
3497 }
3498 }
3499
3500 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3501 if (ret >= 0) {
3502 val = atoi(value);
3503 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3504 ALOGV("invalidate cached edid");
3505 platform_invalidate_edid(adev->platform);
3506 }
3507 }
3508
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003509 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003510
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003511done:
3512 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003513 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303514error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003515 ALOGV("%s: exit with code(%d)", __func__, status);
3516 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517}
3518
3519static char* adev_get_parameters(const struct audio_hw_device *dev,
3520 const char *keys)
3521{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003522 struct audio_device *adev = (struct audio_device *)dev;
3523 struct str_parms *reply = str_parms_create();
3524 struct str_parms *query = str_parms_create_str(keys);
3525 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303526 char value[256] = {0};
3527 int ret = 0;
3528
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003529 if (!query || !reply) {
3530 ALOGE("adev_get_parameters: failed to create query or reply");
3531 return NULL;
3532 }
3533
Naresh Tannirud7205b62014-06-20 02:54:48 +05303534 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3535 sizeof(value));
3536 if (ret >=0) {
3537 int val = 1;
3538 pthread_mutex_lock(&adev->snd_card_status.lock);
3539 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3540 val = 0;
3541 pthread_mutex_unlock(&adev->snd_card_status.lock);
3542 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3543 goto exit;
3544 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003545
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003546 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003547 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003548 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003549 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303550 pthread_mutex_unlock(&adev->lock);
3551
Naresh Tannirud7205b62014-06-20 02:54:48 +05303552exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003553 str = str_parms_to_str(reply);
3554 str_parms_destroy(query);
3555 str_parms_destroy(reply);
3556
3557 ALOGV("%s: exit: returns - %s", __func__, str);
3558 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559}
3560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003561static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
3563 return 0;
3564}
3565
3566static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3567{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003568 int ret;
3569 struct audio_device *adev = (struct audio_device *)dev;
3570 pthread_mutex_lock(&adev->lock);
3571 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003572 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003573 pthread_mutex_unlock(&adev->lock);
3574 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575}
3576
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003577static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3578 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579{
3580 return -ENOSYS;
3581}
3582
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003583static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3584 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585{
3586 return -ENOSYS;
3587}
3588
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003589static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3590 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591{
3592 return -ENOSYS;
3593}
3594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003595static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3596 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597{
3598 return -ENOSYS;
3599}
3600
3601static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3602{
3603 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 pthread_mutex_lock(&adev->lock);
3606 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003607 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003609 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3610 voice_is_in_call(adev)) {
3611 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003612 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003613 adev->current_call_output = NULL;
3614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 }
3616 pthread_mutex_unlock(&adev->lock);
3617 return 0;
3618}
3619
3620static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3621{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003622 int ret;
3623
3624 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003625 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003626 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3627 pthread_mutex_unlock(&adev->lock);
3628
3629 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630}
3631
3632static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3633{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003634 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 return 0;
3636}
3637
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003638static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 const struct audio_config *config)
3640{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003641 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003643 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3644 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645}
3646
3647static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003648 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 audio_devices_t devices,
3650 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003651 struct audio_stream_in **stream_in,
3652 audio_input_flags_t flags __unused,
3653 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003654 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
3656 struct audio_device *adev = (struct audio_device *)dev;
3657 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003658 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003659 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003660 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 *stream_in = NULL;
3663 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3664 return -EINVAL;
3665
3666 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003667
3668 if (!in) {
3669 ALOGE("failed to allocate input stream");
3670 return -ENOMEM;
3671 }
3672
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303673 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003674 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3675 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003677 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003678 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 in->stream.common.get_sample_rate = in_get_sample_rate;
3681 in->stream.common.set_sample_rate = in_set_sample_rate;
3682 in->stream.common.get_buffer_size = in_get_buffer_size;
3683 in->stream.common.get_channels = in_get_channels;
3684 in->stream.common.get_format = in_get_format;
3685 in->stream.common.set_format = in_set_format;
3686 in->stream.common.standby = in_standby;
3687 in->stream.common.dump = in_dump;
3688 in->stream.common.set_parameters = in_set_parameters;
3689 in->stream.common.get_parameters = in_get_parameters;
3690 in->stream.common.add_audio_effect = in_add_audio_effect;
3691 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3692 in->stream.set_gain = in_set_gain;
3693 in->stream.read = in_read;
3694 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3695
3696 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003697 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 in->standby = 1;
3700 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003701 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003702 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703
3704 /* Update config params with the requested sample rate and channels */
3705 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003706 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3707 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3708 is_low_latency = true;
3709#if LOW_LATENCY_CAPTURE_USE_CASE
3710 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3711#endif
3712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003715 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003717 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303718 if (adev->mode != AUDIO_MODE_IN_CALL) {
3719 ret = -EINVAL;
3720 goto err_open;
3721 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003722 if (config->sample_rate == 0)
3723 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3724 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3725 config->sample_rate != 8000) {
3726 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3727 ret = -EINVAL;
3728 goto err_open;
3729 }
3730 if (config->format == AUDIO_FORMAT_DEFAULT)
3731 config->format = AUDIO_FORMAT_PCM_16_BIT;
3732 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3733 config->format = AUDIO_FORMAT_PCM_16_BIT;
3734 ret = -EINVAL;
3735 goto err_open;
3736 }
3737
3738 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3739 in->config = pcm_config_afe_proxy_record;
3740 in->config.channels = channel_count;
3741 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303742 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3743 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003744 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003745 audio_extn_compr_cap_format_supported(config->format) &&
3746 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003747 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003748 } else {
3749 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003750 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003751 buffer_size = get_input_buffer_size(config->sample_rate,
3752 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003753 channel_count,
3754 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003755 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003756 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3757 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3758 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3759 (in->config.rate == 8000 || in->config.rate == 16000) &&
3760 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3761 voice_extn_compress_voip_open_input_stream(in);
3762 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003765 /* This stream could be for sound trigger lab,
3766 get sound trigger pcm if present */
3767 audio_extn_sound_trigger_check_and_get_session(in);
3768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003770 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003771 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
3773err_open:
3774 free(in);
3775 *stream_in = NULL;
3776 return ret;
3777}
3778
3779static void adev_close_input_stream(struct audio_hw_device *dev,
3780 struct audio_stream_in *stream)
3781{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003782 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003783 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003784 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303785
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303786 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003787
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303788 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003789 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303790
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003791 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303792 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003793 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303794 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003795 if (ret != 0)
3796 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3797 __func__, ret);
3798 } else
3799 in_standby(&stream->common);
3800
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003801 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003802 audio_extn_ssr_deinit();
3803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Mingming Yine62d7842013-10-25 16:26:03 -07003805 if(audio_extn_compr_cap_enabled() &&
3806 audio_extn_compr_cap_format_supported(in->config.format))
3807 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003808
3809 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 return;
3811}
3812
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003813static int adev_dump(const audio_hw_device_t *device __unused,
3814 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815{
3816 return 0;
3817}
3818
3819static int adev_close(hw_device_t *device)
3820{
3821 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003822
3823 if (!adev)
3824 return 0;
3825
3826 pthread_mutex_lock(&adev_init_lock);
3827
3828 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003829 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003830 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003831 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003832 audio_route_free(adev->audio_route);
3833 free(adev->snd_dev_ref_cnt);
3834 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003835 if (adev->adm_deinit)
3836 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003837 free(device);
3838 adev = NULL;
3839 }
3840 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842 return 0;
3843}
3844
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003845/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3846 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3847 * just that it _might_ work.
3848 */
3849static int period_size_is_plausible_for_low_latency(int period_size)
3850{
3851 switch (period_size) {
3852 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003853 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003854 case 240:
3855 case 320:
3856 case 480:
3857 return 1;
3858 default:
3859 return 0;
3860 }
3861}
3862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863static int adev_open(const hw_module_t *module, const char *name,
3864 hw_device_t **device)
3865{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003866 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003868 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3870
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003871 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003872 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003873 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003874 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003875 ALOGD("%s: returning existing instance of adev", __func__);
3876 ALOGD("%s: exit", __func__);
3877 pthread_mutex_unlock(&adev_init_lock);
3878 return 0;
3879 }
3880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 adev = calloc(1, sizeof(struct audio_device));
3882
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003883 if (!adev) {
3884 pthread_mutex_unlock(&adev_init_lock);
3885 return -ENOMEM;
3886 }
3887
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003888 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3891 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3892 adev->device.common.module = (struct hw_module_t *)module;
3893 adev->device.common.close = adev_close;
3894
3895 adev->device.init_check = adev_init_check;
3896 adev->device.set_voice_volume = adev_set_voice_volume;
3897 adev->device.set_master_volume = adev_set_master_volume;
3898 adev->device.get_master_volume = adev_get_master_volume;
3899 adev->device.set_master_mute = adev_set_master_mute;
3900 adev->device.get_master_mute = adev_get_master_mute;
3901 adev->device.set_mode = adev_set_mode;
3902 adev->device.set_mic_mute = adev_set_mic_mute;
3903 adev->device.get_mic_mute = adev_get_mic_mute;
3904 adev->device.set_parameters = adev_set_parameters;
3905 adev->device.get_parameters = adev_get_parameters;
3906 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3907 adev->device.open_output_stream = adev_open_output_stream;
3908 adev->device.close_output_stream = adev_close_output_stream;
3909 adev->device.open_input_stream = adev_open_input_stream;
3910 adev->device.close_input_stream = adev_close_input_stream;
3911 adev->device.dump = adev_dump;
3912
3913 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003915 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003916 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003919 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003920 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003921 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003922 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003923 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003924 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003925 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303926 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303927 adev->perf_lock_opts[0] = 0x101;
3928 adev->perf_lock_opts[1] = 0x20E;
3929 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303930
3931 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3932 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003934 adev->platform = platform_init(adev);
3935 if (!adev->platform) {
3936 free(adev->snd_dev_ref_cnt);
3937 free(adev);
3938 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3939 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003940 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003941 return -EINVAL;
3942 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003943
Naresh Tanniru4c630392014-05-12 01:05:52 +05303944 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3945
Eric Laurentc4aef752013-09-12 17:45:53 -07003946 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3947 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3948 if (adev->visualizer_lib == NULL) {
3949 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3950 } else {
3951 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3952 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003953 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003954 "visualizer_hal_start_output");
3955 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003956 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003957 "visualizer_hal_stop_output");
3958 }
3959 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003960 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003961 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003962
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003963 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3964 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3965 if (adev->offload_effects_lib == NULL) {
3966 ALOGE("%s: DLOPEN failed for %s", __func__,
3967 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3968 } else {
3969 ALOGV("%s: DLOPEN successful for %s", __func__,
3970 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3971 adev->offload_effects_start_output =
3972 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3973 "offload_effects_bundle_hal_start_output");
3974 adev->offload_effects_stop_output =
3975 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3976 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003977 adev->offload_effects_set_hpx_state =
3978 (int (*)(bool))dlsym(adev->offload_effects_lib,
3979 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303980 adev->offload_effects_get_parameters =
3981 (void (*)(struct str_parms *, struct str_parms *))
3982 dlsym(adev->offload_effects_lib,
3983 "offload_effects_bundle_get_parameters");
3984 adev->offload_effects_set_parameters =
3985 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3986 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003987 }
3988 }
3989
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003990 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3991 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3992 if (adev->adm_lib == NULL) {
3993 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3994 } else {
3995 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3996 adev->adm_init = (adm_init_t)
3997 dlsym(adev->adm_lib, "adm_init");
3998 adev->adm_deinit = (adm_deinit_t)
3999 dlsym(adev->adm_lib, "adm_deinit");
4000 adev->adm_register_input_stream = (adm_register_input_stream_t)
4001 dlsym(adev->adm_lib, "adm_register_input_stream");
4002 adev->adm_register_output_stream = (adm_register_output_stream_t)
4003 dlsym(adev->adm_lib, "adm_register_output_stream");
4004 adev->adm_deregister_stream = (adm_deregister_stream_t)
4005 dlsym(adev->adm_lib, "adm_deregister_stream");
4006 adev->adm_request_focus = (adm_request_focus_t)
4007 dlsym(adev->adm_lib, "adm_request_focus");
4008 adev->adm_abandon_focus = (adm_abandon_focus_t)
4009 dlsym(adev->adm_lib, "adm_abandon_focus");
4010 }
4011 }
4012
Mingming Yin514a8bc2014-07-29 15:22:21 -07004013 adev->bt_wb_speech_enabled = false;
4014
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004015 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 *device = &adev->device.common;
4017
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004018 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4019 &adev->streams_output_cfg_list);
4020
Kiran Kandi910e1862013-10-29 13:29:42 -07004021 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004022
4023 char value[PROPERTY_VALUE_MAX];
4024 int trial;
4025 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4026 trial = atoi(value);
4027 if (period_size_is_plausible_for_low_latency(trial)) {
4028 pcm_config_low_latency.period_size = trial;
4029 pcm_config_low_latency.start_threshold = trial / 4;
4030 pcm_config_low_latency.avail_min = trial / 4;
4031 configured_low_latency_capture_period_size = trial;
4032 }
4033 }
4034 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4035 trial = atoi(value);
4036 if (period_size_is_plausible_for_low_latency(trial)) {
4037 configured_low_latency_capture_period_size = trial;
4038 }
4039 }
4040
vivek mehta446c3962015-09-14 10:57:35 -07004041 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004042 pthread_mutex_unlock(&adev_init_lock);
4043
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004044 if (adev->adm_init)
4045 adev->adm_data = adev->adm_init();
4046
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304047 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004048 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 return 0;
4050}
4051
4052static struct hw_module_methods_t hal_module_methods = {
4053 .open = adev_open,
4054};
4055
4056struct audio_module HAL_MODULE_INFO_SYM = {
4057 .common = {
4058 .tag = HARDWARE_MODULE_TAG,
4059 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4060 .hal_api_version = HARDWARE_HAL_API_VERSION,
4061 .id = AUDIO_HARDWARE_MODULE_ID,
4062 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004063 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064 .methods = &hal_module_methods,
4065 },
4066};