blob: a0f9206e67d0f98bc6ac7f90797d836a407d1d51 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700508 if (audio_extn_spkr_prot_is_enabled())
509 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700510 /* start usb playback thread */
511 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
512 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
513 audio_extn_usb_start_playback(adev);
514
515 /* start usb capture thread */
516 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
517 audio_extn_usb_start_capture(adev);
518
Preetam Singh Ranawat61716b12015-12-14 11:55:24 +0530519 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530520 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800521 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700522 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
524 adev->snd_dev_ref_cnt[snd_device]--;
525 return -EINVAL;
526 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200527 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800528 if (audio_extn_spkr_prot_start_processing(snd_device)) {
529 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200530 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800531 return -EINVAL;
532 }
533 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700534 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700535 /* due to the possibility of calibration overwrite between listen
536 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700537 audio_extn_sound_trigger_update_device_status(snd_device,
538 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530539 audio_extn_listen_update_device_status(snd_device,
540 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700541 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700542 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700543 audio_extn_sound_trigger_update_device_status(snd_device,
544 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530545 audio_extn_listen_update_device_status(snd_device,
546 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700547 return -EINVAL;
548 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300549 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700550 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 return 0;
553}
554
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700555int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700556 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700558 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
559
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800560 if (snd_device < SND_DEVICE_MIN ||
561 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800562 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800563 return -EINVAL;
564 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
566 ALOGE("%s: device ref cnt is already 0", __func__);
567 return -EINVAL;
568 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700569
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700571
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700572 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
573 ALOGE("%s: Invalid sound device returned", __func__);
574 return -EINVAL;
575 }
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700578 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800579 /* exit usb play back thread */
580 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
581 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
582 audio_extn_usb_stop_playback();
583
584 /* exit usb capture thread */
585 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700586 audio_extn_usb_stop_capture();
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530587 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530588 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800589 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700590 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700591 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300592 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700593 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300594 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700595
Ashish Jain81eb2a82015-05-13 10:52:34 +0530596 if (snd_device == SND_DEVICE_OUT_HDMI)
597 adev->is_channel_status_set = false;
598
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200599 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700600 audio_extn_sound_trigger_update_device_status(snd_device,
601 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530602 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800603 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700604 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800606 return 0;
607}
608
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609static void check_usecases_codec_backend(struct audio_device *adev,
610 struct audio_usecase *uc_info,
611 snd_device_t snd_device)
612{
613 struct listnode *node;
614 struct audio_usecase *usecase;
615 bool switch_device[AUDIO_USECASE_MAX];
616 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800617 int backend_idx = DEFAULT_CODEC_BACKEND;
618 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619
620 /*
621 * This function is to make sure that all the usecases that are active on
622 * the hardware codec backend are always routed to any one device that is
623 * handled by the hardware codec.
624 * For example, if low-latency and deep-buffer usecases are currently active
625 * on speaker and out_set_parameters(headset) is received on low-latency
626 * output, then we have to make sure deep-buffer is also switched to headset,
627 * because of the limitation that both the devices cannot be enabled
628 * at the same time as they share the same backend.
629 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700630 /*
631 * This call is to check if we need to force routing for a particular stream
632 * If there is a backend configuration change for the device when a
633 * new stream starts, then ADM needs to be closed and re-opened with the new
634 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800635 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700636 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800637 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
638 snd_device);
639 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800641 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800642 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 for (i = 0; i < AUDIO_USECASE_MAX; i++)
644 switch_device[i] = false;
645
646 list_for_each(node, &adev->usecase_list) {
647 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800648
649 if (usecase == uc_info)
650 continue;
651 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
652 ALOGV("%s: backend_idx: %d,"
653 "usecase_backend_idx: %d, curr device: %s, usecase device:"
654 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatc61f8672015-06-18 23:20:28 +0530655 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800656
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800657 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700658 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800659 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
660 usecase_backend_idx == backend_idx) {
Sidipotu Ashok894644d2015-07-06 18:35:03 +0530661 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800662 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700663 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700664 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 switch_device[usecase->id] = true;
666 num_uc_to_switch++;
667 }
668 }
669
670 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700671 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530673 /* Make sure the previous devices to be disabled first and then enable the
674 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 list_for_each(node, &adev->usecase_list) {
676 usecase = node_to_item(node, struct audio_usecase, list);
677 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700678 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 }
680 }
681
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700682 list_for_each(node, &adev->usecase_list) {
683 usecase = node_to_item(node, struct audio_usecase, list);
684 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700686 }
687 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 /* Re-route all the usecases on the shared backend other than the
690 specified usecase to new snd devices */
691 list_for_each(node, &adev->usecase_list) {
692 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530693 /* Update the out_snd_device only for the usecases that are enabled here */
694 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
695 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530696 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700697 }
698 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 }
700}
701
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700702static void check_and_route_capture_usecases(struct audio_device *adev,
703 struct audio_usecase *uc_info,
704 snd_device_t snd_device)
705{
706 struct listnode *node;
707 struct audio_usecase *usecase;
708 bool switch_device[AUDIO_USECASE_MAX];
709 int i, num_uc_to_switch = 0;
710
711 /*
712 * This function is to make sure that all the active capture usecases
713 * are always routed to the same input sound device.
714 * For example, if audio-record and voice-call usecases are currently
715 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
716 * is received for voice call then we have to make sure that audio-record
717 * usecase is also switched to earpiece i.e. voice-dmic-ef,
718 * because of the limitation that two devices cannot be enabled
719 * at the same time if they share the same backend.
720 */
721 for (i = 0; i < AUDIO_USECASE_MAX; i++)
722 switch_device[i] = false;
723
724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800726 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700728 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700729 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
730 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700731 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700732 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
733 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700734 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 switch_device[usecase->id] = true;
737 num_uc_to_switch++;
738 }
739 }
740
741 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700742 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700743
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530744 /* Make sure the previous devices to be disabled first and then enable the
745 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700746 list_for_each(node, &adev->usecase_list) {
747 usecase = node_to_item(node, struct audio_usecase, list);
748 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700749 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800750 }
751 }
752
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700756 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700757 }
758 }
759
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 /* Re-route all the usecases on the shared backend other than the
761 specified usecase to new snd devices */
762 list_for_each(node, &adev->usecase_list) {
763 usecase = node_to_item(node, struct audio_usecase, list);
764 /* Update the in_snd_device only before enabling the audio route */
765 if (switch_device[usecase->id] ) {
766 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800767 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530768 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700769 }
770 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700771 }
772}
773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700775static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700777 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700778 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779
780 switch (channels) {
781 /*
782 * Do not handle stereo output in Multi-channel cases
783 * Stereo case is handled in normal playback path
784 */
785 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700786 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792 break;
793 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700794 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
795 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
796 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
797 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
798 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
799 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
800 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800801 break;
802 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700803 ALOGE("HDMI does not support multi channel playback");
804 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805 break;
806 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700807 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808}
809
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800810audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
811 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700812{
813 struct audio_usecase *usecase;
814 struct listnode *node;
815
816 list_for_each(node, &adev->usecase_list) {
817 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800818 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700819 ALOGV("%s: usecase id %d", __func__, usecase->id);
820 return usecase->id;
821 }
822 }
823 return USECASE_INVALID;
824}
825
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700826struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700827 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828{
829 struct audio_usecase *usecase;
830 struct listnode *node;
831
832 list_for_each(node, &adev->usecase_list) {
833 usecase = node_to_item(node, struct audio_usecase, list);
834 if (usecase->id == uc_id)
835 return usecase;
836 }
837 return NULL;
838}
839
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700840int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800842 snd_device_t out_snd_device = SND_DEVICE_NONE;
843 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 struct audio_usecase *usecase = NULL;
845 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800846 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800847 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800848 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800849 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 usecase = get_usecase_from_list(adev, uc_id);
853 if (usecase == NULL) {
854 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
855 return -EINVAL;
856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800858 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800859 (usecase->type == VOIP_CALL) ||
860 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700861 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800862 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700863 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 usecase->devices = usecase->stream.out->devices;
865 } else {
866 /*
867 * If the voice call is active, use the sound devices of voice call usecase
868 * so that it would not result any device switch. All the usecases will
869 * be switched to new device when select_devices() is called for voice call
870 * usecase. This is to avoid switching devices for voice call when
871 * check_usecases_codec_backend() is called below.
872 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700873 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700874 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800875 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700876 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
877 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 in_snd_device = vc_usecase->in_snd_device;
879 out_snd_device = vc_usecase->out_snd_device;
880 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800881 } else if (voice_extn_compress_voip_is_active(adev)) {
882 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700883 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530884 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700885 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800886 in_snd_device = voip_usecase->in_snd_device;
887 out_snd_device = voip_usecase->out_snd_device;
888 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800889 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800890 hfp_ucid = audio_extn_hfp_get_usecase();
891 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700892 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800893 in_snd_device = hfp_usecase->in_snd_device;
894 out_snd_device = hfp_usecase->out_snd_device;
895 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 }
897 if (usecase->type == PCM_PLAYBACK) {
898 usecase->devices = usecase->stream.out->devices;
899 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800902 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700903 if (usecase->stream.out == adev->primary_output &&
904 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800905 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700906 select_devices(adev, adev->active_input->usecase);
907 }
908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 } else if (usecase->type == PCM_CAPTURE) {
910 usecase->devices = usecase->stream.in->device;
911 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700912 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700913 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530914 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
915 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
916 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
917 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700918 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -0700919 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700920 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
921 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700922 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700923 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700924 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 }
926 }
927
928 if (out_snd_device == usecase->out_snd_device &&
929 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800930 return 0;
931 }
932
sangwoobc677242013-08-08 16:53:43 +0900933 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700934 out_snd_device, platform_get_snd_device_name(out_snd_device),
935 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 /*
938 * Limitation: While in call, to do a device switch we need to disable
939 * and enable both RX and TX devices though one of them is same as current
940 * device.
941 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700942 if ((usecase->type == VOICE_CALL) &&
943 (usecase->in_snd_device != SND_DEVICE_NONE) &&
944 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700945 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700946 }
947
948 if (((usecase->type == VOICE_CALL) ||
949 (usecase->type == VOIP_CALL)) &&
950 (usecase->out_snd_device != SND_DEVICE_NONE)) {
951 /* Disable sidetone only if voice/voip call already exists */
952 if (voice_is_call_state_active(adev) ||
953 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -0700954 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800955 }
956
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700957 /* Disable current sound devices */
958 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700959 disable_audio_route(adev, usecase);
960 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961 }
962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700964 disable_audio_route(adev, usecase);
965 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 }
967
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800968 /* Applicable only on the targets that has external modem.
969 * New device information should be sent to modem before enabling
970 * the devices to reduce in-call device switch time.
971 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700972 if ((usecase->type == VOICE_CALL) &&
973 (usecase->in_snd_device != SND_DEVICE_NONE) &&
974 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800975 status = platform_switch_voice_call_enable_device_config(adev->platform,
976 out_snd_device,
977 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700978 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800979
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 /* Enable new sound devices */
981 if (out_snd_device != SND_DEVICE_NONE) {
982 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
983 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700984 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 }
986
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 if (in_snd_device != SND_DEVICE_NONE) {
988 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700989 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991
Avinash Vaish71a8b972014-07-24 15:36:33 +0530992 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700993 status = platform_switch_voice_call_device_post(adev->platform,
994 out_snd_device,
995 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530996 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -0700997 /* Enable sidetone only if voice/voip call already exists */
998 if (voice_is_call_state_active(adev) ||
999 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001000 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301001 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001002
sangwoo170731f2013-06-08 15:36:36 +09001003 usecase->in_snd_device = in_snd_device;
1004 usecase->out_snd_device = out_snd_device;
1005
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301006 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001007 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301008 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001009 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301010 usecase->stream.out->flags,
1011 usecase->stream.out->format,
1012 usecase->stream.out->sample_rate,
1013 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301014 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301015 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001016 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301017 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001018
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001019 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001020
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001021 /* Applicable only on the targets that has external modem.
1022 * Enable device command should be sent to modem only after
1023 * enabling voice call mixer controls
1024 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001025 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001026 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1027 out_snd_device,
1028 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301029 ALOGD("%s: done",__func__);
1030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 return status;
1032}
1033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034static int stop_input_stream(struct stream_in *in)
1035{
1036 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037 struct audio_usecase *uc_info;
1038 struct audio_device *adev = in->dev;
1039
Eric Laurentc8400632013-02-14 19:04:54 -08001040 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041
Eric Laurent994a6932013-07-17 11:51:42 -07001042 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044 uc_info = get_usecase_from_list(adev, in->usecase);
1045 if (uc_info == NULL) {
1046 ALOGE("%s: Could not find the usecase (%d) in the list",
1047 __func__, in->usecase);
1048 return -EINVAL;
1049 }
1050
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001051 /* Close in-call recording streams */
1052 voice_check_and_stop_incall_rec_usecase(adev, in);
1053
Eric Laurent150dbfe2013-02-27 14:31:02 -08001054 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001055 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056
1057 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001058 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001060 list_remove(&uc_info->list);
1061 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062
Eric Laurent994a6932013-07-17 11:51:42 -07001063 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 return ret;
1065}
1066
1067int start_input_stream(struct stream_in *in)
1068{
1069 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001070 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 struct audio_usecase *uc_info;
1072 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301073 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074
Mingming Yin2664a5b2015-09-03 10:53:11 -07001075 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1076 if (get_usecase_from_list(adev, usecase) == NULL)
1077 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301078 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1079 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001080
Naresh Tanniru80659832014-06-04 18:17:56 +05301081
1082 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301083 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301084 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301085 goto error_config;
1086 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001088 /* Check if source matches incall recording usecase criteria */
1089 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1090 if (ret)
1091 goto error_config;
1092 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001093 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1094
1095 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1096 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1097 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1098 goto error_config;
1099 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001100
Eric Laurentb23d5282013-05-14 15:27:20 -07001101 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102 if (in->pcm_device_id < 0) {
1103 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1104 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001105 ret = -EINVAL;
1106 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001107 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108
1109 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001111
1112 if (!uc_info) {
1113 ret = -ENOMEM;
1114 goto error_config;
1115 }
1116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 uc_info->id = in->usecase;
1118 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001119 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 uc_info->devices = in->device;
1121 uc_info->in_snd_device = SND_DEVICE_NONE;
1122 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001124 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301125 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1126 adev->perf_lock_opts,
1127 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129
Eric Laurentc8400632013-02-14 19:04:54 -08001130 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001131 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1132
1133 unsigned int flags = PCM_IN;
1134 unsigned int pcm_open_retry_count = 0;
1135
1136 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1137 flags |= PCM_MMAP | PCM_NOIRQ;
1138 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1139 }
1140
1141 while (1) {
1142 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1143 flags, &in->config);
1144 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1145 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1146 if (in->pcm != NULL) {
1147 pcm_close(in->pcm);
1148 in->pcm = NULL;
1149 }
1150 if (pcm_open_retry_count-- == 0) {
1151 ret = -EIO;
1152 goto error_open;
1153 }
1154 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1155 continue;
1156 }
1157 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001159
1160 ALOGV("%s: pcm_prepare", __func__);
1161 ret = pcm_prepare(in->pcm);
1162 if (ret < 0) {
1163 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1164 pcm_close(in->pcm);
1165 in->pcm = NULL;
1166 goto error_open;
1167 }
1168
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301169 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001170 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001171
Eric Laurentc8400632013-02-14 19:04:54 -08001172 return ret;
1173
1174error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301175 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001177error_config:
1178 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301179 /*
1180 * sleep 50ms to allow sufficient time for kernel
1181 * drivers to recover incases like SSR.
1182 */
1183 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001185
1186 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187}
1188
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001189void lock_input_stream(struct stream_in *in)
1190{
1191 pthread_mutex_lock(&in->pre_lock);
1192 pthread_mutex_lock(&in->lock);
1193 pthread_mutex_unlock(&in->pre_lock);
1194}
1195
1196void lock_output_stream(struct stream_out *out)
1197{
1198 pthread_mutex_lock(&out->pre_lock);
1199 pthread_mutex_lock(&out->lock);
1200 pthread_mutex_unlock(&out->pre_lock);
1201}
1202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203/* must be called with out->lock locked */
1204static int send_offload_cmd_l(struct stream_out* out, int command)
1205{
1206 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1207
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001208 if (!cmd) {
1209 ALOGE("failed to allocate mem for command 0x%x", command);
1210 return -ENOMEM;
1211 }
1212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001213 ALOGVV("%s %d", __func__, command);
1214
1215 cmd->cmd = command;
1216 list_add_tail(&out->offload_cmd_list, &cmd->node);
1217 pthread_cond_signal(&out->offload_cond);
1218 return 0;
1219}
1220
1221/* must be called iwth out->lock locked */
1222static void stop_compressed_output_l(struct stream_out *out)
1223{
1224 out->offload_state = OFFLOAD_STATE_IDLE;
1225 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001226 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001227 if (out->compr != NULL) {
1228 compress_stop(out->compr);
1229 while (out->offload_thread_blocked) {
1230 pthread_cond_wait(&out->cond, &out->lock);
1231 }
1232 }
1233}
1234
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001235bool is_offload_usecase(audio_usecase_t uc_id)
1236{
1237 unsigned int i;
1238 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1239 if (uc_id == offload_usecases[i])
1240 return true;
1241 }
1242 return false;
1243}
1244
vivek mehta446c3962015-09-14 10:57:35 -07001245static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001246{
vivek mehta446c3962015-09-14 10:57:35 -07001247 audio_usecase_t ret_uc = USECASE_INVALID;
1248 unsigned int offload_uc_index;
1249 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1250 if (!adev->multi_offload_enable) {
1251 if (is_direct_pcm)
1252 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1253 else
1254 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001255
vivek mehta446c3962015-09-14 10:57:35 -07001256 pthread_mutex_lock(&adev->lock);
1257 if (get_usecase_from_list(adev, ret_uc) != NULL)
1258 ret_uc = USECASE_INVALID;
1259 pthread_mutex_unlock(&adev->lock);
1260
1261 return ret_uc;
1262 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001263
1264 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001265 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1266 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1267 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1268 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001269 break;
1270 }
1271 }
vivek mehta446c3962015-09-14 10:57:35 -07001272
1273 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1274 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001275}
1276
1277static void free_offload_usecase(struct audio_device *adev,
1278 audio_usecase_t uc_id)
1279{
vivek mehta446c3962015-09-14 10:57:35 -07001280 unsigned int offload_uc_index;
1281 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1282
1283 if (!adev->multi_offload_enable)
1284 return;
1285
1286 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1287 if (offload_usecases[offload_uc_index] == uc_id) {
1288 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001289 break;
1290 }
1291 }
1292 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1293}
1294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295static void *offload_thread_loop(void *context)
1296{
1297 struct stream_out *out = (struct stream_out *) context;
1298 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001299 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1302 set_sched_policy(0, SP_FOREGROUND);
1303 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1304
1305 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001306 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 for (;;) {
1308 struct offload_cmd *cmd = NULL;
1309 stream_callback_event_t event;
1310 bool send_callback = false;
1311
1312 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1313 __func__, list_empty(&out->offload_cmd_list),
1314 out->offload_state);
1315 if (list_empty(&out->offload_cmd_list)) {
1316 ALOGV("%s SLEEPING", __func__);
1317 pthread_cond_wait(&out->offload_cond, &out->lock);
1318 ALOGV("%s RUNNING", __func__);
1319 continue;
1320 }
1321
1322 item = list_head(&out->offload_cmd_list);
1323 cmd = node_to_item(item, struct offload_cmd, node);
1324 list_remove(item);
1325
1326 ALOGVV("%s STATE %d CMD %d out->compr %p",
1327 __func__, out->offload_state, cmd->cmd, out->compr);
1328
1329 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1330 free(cmd);
1331 break;
1332 }
1333
1334 if (out->compr == NULL) {
1335 ALOGE("%s: Compress handle is NULL", __func__);
1336 pthread_cond_signal(&out->cond);
1337 continue;
1338 }
1339 out->offload_thread_blocked = true;
1340 pthread_mutex_unlock(&out->lock);
1341 send_callback = false;
1342 switch(cmd->cmd) {
1343 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001344 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001345 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001346 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 send_callback = true;
1348 event = STREAM_CBK_EVENT_WRITE_READY;
1349 break;
1350 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001351 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301352 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001353 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301354 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001355 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301356 if (ret < 0)
1357 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301358 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301359 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001360 compress_drain(out->compr);
1361 else
1362 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301363 if (ret != -ENETRESET) {
1364 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301365 pthread_mutex_lock(&out->lock);
1366 out->send_new_metadata = 1;
1367 out->send_next_track_params = true;
1368 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301369 event = STREAM_CBK_EVENT_DRAIN_READY;
1370 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1371 } else
1372 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001373 break;
1374 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001375 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001376 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001377 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001378 send_callback = true;
1379 event = STREAM_CBK_EVENT_DRAIN_READY;
1380 break;
1381 default:
1382 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1383 break;
1384 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001385 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001386 out->offload_thread_blocked = false;
1387 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001388 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001389 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001390 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001391 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392 free(cmd);
1393 }
1394
1395 pthread_cond_signal(&out->cond);
1396 while (!list_empty(&out->offload_cmd_list)) {
1397 item = list_head(&out->offload_cmd_list);
1398 list_remove(item);
1399 free(node_to_item(item, struct offload_cmd, node));
1400 }
1401 pthread_mutex_unlock(&out->lock);
1402
1403 return NULL;
1404}
1405
1406static int create_offload_callback_thread(struct stream_out *out)
1407{
1408 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1409 list_init(&out->offload_cmd_list);
1410 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1411 offload_thread_loop, out);
1412 return 0;
1413}
1414
1415static int destroy_offload_callback_thread(struct stream_out *out)
1416{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001417 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001418 stop_compressed_output_l(out);
1419 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1420
1421 pthread_mutex_unlock(&out->lock);
1422 pthread_join(out->offload_thread, (void **) NULL);
1423 pthread_cond_destroy(&out->offload_cond);
1424
1425 return 0;
1426}
1427
Eric Laurent07eeafd2013-10-06 12:52:49 -07001428static bool allow_hdmi_channel_config(struct audio_device *adev)
1429{
1430 struct listnode *node;
1431 struct audio_usecase *usecase;
1432 bool ret = true;
1433
1434 list_for_each(node, &adev->usecase_list) {
1435 usecase = node_to_item(node, struct audio_usecase, list);
1436 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1437 /*
1438 * If voice call is already existing, do not proceed further to avoid
1439 * disabling/enabling both RX and TX devices, CSD calls, etc.
1440 * Once the voice call done, the HDMI channels can be configured to
1441 * max channels of remaining use cases.
1442 */
1443 if (usecase->id == USECASE_VOICE_CALL) {
1444 ALOGD("%s: voice call is active, no change in HDMI channels",
1445 __func__);
1446 ret = false;
1447 break;
1448 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1449 ALOGD("%s: multi channel playback is active, "
1450 "no change in HDMI channels", __func__);
1451 ret = false;
1452 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001453 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001454 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001455 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1456 ", no change in HDMI channels", __func__,
1457 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001458 ret = false;
1459 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001460 }
1461 }
1462 }
1463 return ret;
1464}
1465
1466static int check_and_set_hdmi_channels(struct audio_device *adev,
1467 unsigned int channels)
1468{
1469 struct listnode *node;
1470 struct audio_usecase *usecase;
1471
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001472 unsigned int supported_channels = platform_edid_get_max_channels(
1473 adev->platform);
1474 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001475 /* Check if change in HDMI channel config is allowed */
1476 if (!allow_hdmi_channel_config(adev))
1477 return 0;
1478
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001479 if (channels > supported_channels)
1480 channels = supported_channels;
1481
Eric Laurent07eeafd2013-10-06 12:52:49 -07001482 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001483 ALOGD("%s: Requested channels are same as current channels(%d)",
1484 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001485 return 0;
1486 }
1487
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001488 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001489 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001490 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001491 adev->cur_hdmi_channels = channels;
1492
1493 /*
1494 * Deroute all the playback streams routed to HDMI so that
1495 * the back end is deactivated. Note that backend will not
1496 * be deactivated if any one stream is connected to it.
1497 */
1498 list_for_each(node, &adev->usecase_list) {
1499 usecase = node_to_item(node, struct audio_usecase, list);
1500 if (usecase->type == PCM_PLAYBACK &&
1501 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001502 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001503 }
1504 }
1505
1506 /*
1507 * Enable all the streams disabled above. Now the HDMI backend
1508 * will be activated with new channel configuration
1509 */
1510 list_for_each(node, &adev->usecase_list) {
1511 usecase = node_to_item(node, struct audio_usecase, list);
1512 if (usecase->type == PCM_PLAYBACK &&
1513 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001514 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001515 }
1516 }
1517
1518 return 0;
1519}
1520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521static int stop_output_stream(struct stream_out *out)
1522{
1523 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 struct audio_usecase *uc_info;
1525 struct audio_device *adev = out->dev;
1526
Eric Laurent994a6932013-07-17 11:51:42 -07001527 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 uc_info = get_usecase_from_list(adev, out->usecase);
1530 if (uc_info == NULL) {
1531 ALOGE("%s: Could not find the usecase (%d) in the list",
1532 __func__, out->usecase);
1533 return -EINVAL;
1534 }
1535
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001536 if (is_offload_usecase(out->usecase) &&
1537 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001538 if (adev->visualizer_stop_output != NULL)
1539 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001540
1541 audio_extn_dts_remove_state_notifier_node(out->usecase);
1542
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001543 if (adev->offload_effects_stop_output != NULL)
1544 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1545 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001546
Eric Laurent150dbfe2013-02-27 14:31:02 -08001547 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001548 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001549
1550 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001551 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001553 list_remove(&uc_info->list);
1554 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001556 if (is_offload_usecase(out->usecase) &&
1557 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1558 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1559 ALOGV("Disable passthrough , reset mixer to pcm");
1560 /* NO_PASSTHROUGH */
1561 out->compr_config.codec->compr_passthr = 0;
1562 audio_extn_dolby_set_hdmi_config(adev, out);
1563 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1564 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001565 /* Must be called after removing the usecase from list */
1566 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1567 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1568
Eric Laurent994a6932013-07-17 11:51:42 -07001569 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 return ret;
1571}
1572
1573int start_output_stream(struct stream_out *out)
1574{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001576 int sink_channels = 0;
1577 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 struct audio_usecase *uc_info;
1579 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301580 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001582 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1583 ret = -EINVAL;
1584 goto error_config;
1585 }
1586
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301587 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1588 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1589 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301590
Naresh Tanniru80659832014-06-04 18:17:56 +05301591 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301592 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301593 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301594 goto error_config;
1595 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301596
Eric Laurentb23d5282013-05-14 15:27:20 -07001597 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 if (out->pcm_device_id < 0) {
1599 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1600 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001601 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001602 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 }
1604
1605 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001606
1607 if (!uc_info) {
1608 ret = -ENOMEM;
1609 goto error_config;
1610 }
1611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 uc_info->id = out->usecase;
1613 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001614 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001615 uc_info->devices = out->devices;
1616 uc_info->in_snd_device = SND_DEVICE_NONE;
1617 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001618 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001619 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001620 if (is_offload_usecase(out->usecase)) {
1621 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001622 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1623 }
1624 }
Mingming Yin9c041392014-05-01 15:37:31 -07001625 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1626 if (!strncmp("true", prop_value, 4)) {
1627 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001628 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1629 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001630 check_and_set_hdmi_channels(adev, sink_channels);
1631 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001632 if (is_offload_usecase(out->usecase)) {
1633 unsigned int ch_count = out->compr_config.codec->ch_in;
1634 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1635 /* backend channel config for passthrough stream is stereo */
1636 ch_count = 2;
1637 check_and_set_hdmi_channels(adev, ch_count);
1638 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001639 check_and_set_hdmi_channels(adev, out->config.channels);
1640 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001641 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001642 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001643 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301645 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1646 adev->perf_lock_opts,
1647 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 select_devices(adev, out->usecase);
1649
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001650 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1651 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001652 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001653 unsigned int flags = PCM_OUT;
1654 unsigned int pcm_open_retry_count = 0;
1655 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1656 flags |= PCM_MMAP | PCM_NOIRQ;
1657 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1658 } else
1659 flags |= PCM_MONOTONIC;
1660
1661 while (1) {
1662 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1663 flags, &out->config);
1664 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1665 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1666 if (out->pcm != NULL) {
1667 pcm_close(out->pcm);
1668 out->pcm = NULL;
1669 }
1670 if (pcm_open_retry_count-- == 0) {
1671 ret = -EIO;
1672 goto error_open;
1673 }
1674 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1675 continue;
1676 }
1677 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001678 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001679
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001680 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1681 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001682
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001683 ALOGV("%s: pcm_prepare", __func__);
1684 if (pcm_is_ready(out->pcm)) {
1685 ret = pcm_prepare(out->pcm);
1686 if (ret < 0) {
1687 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1688 pcm_close(out->pcm);
1689 out->pcm = NULL;
1690 goto error_open;
1691 }
1692 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001693 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001694 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1695 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001697 out->compr = compress_open(adev->snd_card,
1698 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 COMPRESS_IN, &out->compr_config);
1700 if (out->compr && !is_compress_ready(out->compr)) {
1701 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1702 compress_close(out->compr);
1703 out->compr = NULL;
1704 ret = -EIO;
1705 goto error_open;
1706 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301707 /* compress_open sends params of the track, so reset the flag here */
1708 out->is_compr_metadata_avail = false;
1709
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 if (out->offload_callback)
1711 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001712
Fred Oh3f43e742015-03-04 18:42:34 -08001713 /* Since small bufs uses blocking writes, a write will be blocked
1714 for the default max poll time (20s) in the event of an SSR.
1715 Reduce the poll time to observe and deal with SSR faster.
1716 */
1717 if (out->use_small_bufs) {
1718 compress_set_max_poll_wait(out->compr, 1000);
1719 }
1720
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001721 audio_extn_dts_create_state_notifier_node(out->usecase);
1722 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1723 popcount(out->channel_mask),
1724 out->playback_started);
1725
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001726#ifdef DS1_DOLBY_DDP_ENABLED
1727 if (audio_extn_is_dolby_format(out->format))
1728 audio_extn_dolby_send_ddp_endp_params(adev);
1729#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001730 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1731 if (adev->visualizer_start_output != NULL)
1732 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1733 if (adev->offload_effects_start_output != NULL)
1734 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001735 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301738 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001739 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301743 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001745error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301746 /*
1747 * sleep 50ms to allow sufficient time for kernel
1748 * drivers to recover incases like SSR.
1749 */
1750 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001751 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752}
1753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754static int check_input_parameters(uint32_t sample_rate,
1755 audio_format_t format,
1756 int channel_count)
1757{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001758 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001760 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001761 !voice_extn_compress_voip_is_format_supported(format) &&
1762 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001763
1764 switch (channel_count) {
1765 case 1:
1766 case 2:
1767 case 6:
1768 break;
1769 default:
1770 ret = -EINVAL;
1771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
1773 switch (sample_rate) {
1774 case 8000:
1775 case 11025:
1776 case 12000:
1777 case 16000:
1778 case 22050:
1779 case 24000:
1780 case 32000:
1781 case 44100:
1782 case 48000:
1783 break;
1784 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001785 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 }
1787
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001788 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789}
1790
1791static size_t get_input_buffer_size(uint32_t sample_rate,
1792 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001793 int channel_count,
1794 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795{
1796 size_t size = 0;
1797
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001798 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1799 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001801 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001802 if (is_low_latency)
1803 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001804 /* ToDo: should use frame_size computed based on the format and
1805 channel_count here. */
1806 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001808 /* make sure the size is multiple of 32 bytes
1809 * At 48 kHz mono 16-bit PCM:
1810 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1811 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1812 */
1813 size += 0x1f;
1814 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001815
1816 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817}
1818
1819static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1820{
1821 struct stream_out *out = (struct stream_out *)stream;
1822
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001823 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824}
1825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001826static int out_set_sample_rate(struct audio_stream *stream __unused,
1827 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828{
1829 return -ENOSYS;
1830}
1831
1832static size_t out_get_buffer_size(const struct audio_stream *stream)
1833{
1834 struct stream_out *out = (struct stream_out *)stream;
1835
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001836 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001838 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1839 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001840
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001841 return out->config.period_size *
1842 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843}
1844
1845static uint32_t out_get_channels(const struct audio_stream *stream)
1846{
1847 struct stream_out *out = (struct stream_out *)stream;
1848
1849 return out->channel_mask;
1850}
1851
1852static audio_format_t out_get_format(const struct audio_stream *stream)
1853{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001854 struct stream_out *out = (struct stream_out *)stream;
1855
1856 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857}
1858
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001859static int out_set_format(struct audio_stream *stream __unused,
1860 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861{
1862 return -ENOSYS;
1863}
1864
1865static int out_standby(struct audio_stream *stream)
1866{
1867 struct stream_out *out = (struct stream_out *)stream;
1868 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301870 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1871 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001872 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1873 /* Ignore standby in case of voip call because the voip output
1874 * stream is closed in adev_close_output_stream()
1875 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301876 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001877 return 0;
1878 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001880 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001882 if (adev->adm_deregister_stream)
1883 adev->adm_deregister_stream(adev->adm_data, out->handle);
1884
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001885 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001887 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888 if (out->pcm) {
1889 pcm_close(out->pcm);
1890 out->pcm = NULL;
1891 }
1892 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001893 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001894 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301895 out->send_next_track_params = false;
1896 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001897 out->gapless_mdata.encoder_delay = 0;
1898 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001899 if (out->compr != NULL) {
1900 compress_close(out->compr);
1901 out->compr = NULL;
1902 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001903 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001905 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
1907 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001908 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909 return 0;
1910}
1911
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001912static int out_dump(const struct audio_stream *stream __unused,
1913 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914{
1915 return 0;
1916}
1917
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001918static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1919{
1920 int ret = 0;
1921 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001922
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001923 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001924 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001925 return -EINVAL;
1926 }
1927
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301928 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001929
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001930 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1931 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301932 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001933 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1935 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301936 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001937 }
1938
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001939 ALOGV("%s new encoder delay %u and padding %u", __func__,
1940 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1941
1942 return 0;
1943}
1944
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001945static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1946{
1947 return out == adev->primary_output || out == adev->voice_tx_output;
1948}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1951{
1952 struct stream_out *out = (struct stream_out *)stream;
1953 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001954 struct audio_usecase *usecase;
1955 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 struct str_parms *parms;
1957 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001958 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001959 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960
sangwoobc677242013-08-08 16:53:43 +09001961 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001962 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301964 if (!parms)
1965 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001966 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1967 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001969 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001970 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001972 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301973 * When HDMI cable is unplugged/usb hs is disconnected the
1974 * music playback is paused and the policy manager sends routing=0
1975 * But the audioflingercontinues to write data until standby time
1976 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001977 * Avoid this by routing audio to speaker until standby.
1978 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301979 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1980 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001982 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1983 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001984 }
1985
1986 /*
1987 * select_devices() call below switches all the usecases on the same
1988 * backend to the new device. Refer to check_usecases_codec_backend() in
1989 * the select_devices(). But how do we undo this?
1990 *
1991 * For example, music playback is active on headset (deep-buffer usecase)
1992 * and if we go to ringtones and select a ringtone, low-latency usecase
1993 * will be started on headset+speaker. As we can't enable headset+speaker
1994 * and headset devices at the same time, select_devices() switches the music
1995 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1996 * So when the ringtone playback is completed, how do we undo the same?
1997 *
1998 * We are relying on the out_set_parameters() call on deep-buffer output,
1999 * once the ringtone playback is ended.
2000 * NOTE: We should not check if the current devices are same as new devices.
2001 * Because select_devices() must be called to switch back the music
2002 * playback to headset.
2003 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002004 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002005 out->devices = val;
2006
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302007 if (!out->standby) {
2008 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2009 adev->perf_lock_opts,
2010 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002011 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302012 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2013 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002014
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002015 if (output_drives_call(adev, out)) {
2016 if(!voice_is_in_call(adev)) {
2017 if (adev->mode == AUDIO_MODE_IN_CALL) {
2018 adev->current_call_output = out;
2019 ret = voice_start_call(adev);
2020 }
2021 } else {
2022 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002023 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002024 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002025 }
2026 }
2027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002029 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002031
2032 if (out == adev->primary_output) {
2033 pthread_mutex_lock(&adev->lock);
2034 audio_extn_set_parameters(adev, parms);
2035 pthread_mutex_unlock(&adev->lock);
2036 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002037 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002038 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002039 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002040
2041 audio_extn_dts_create_state_notifier_node(out->usecase);
2042 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2043 popcount(out->channel_mask),
2044 out->playback_started);
2045
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002046 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002047 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302050error:
Eric Laurent994a6932013-07-17 11:51:42 -07002051 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 return ret;
2053}
2054
2055static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2056{
2057 struct stream_out *out = (struct stream_out *)stream;
2058 struct str_parms *query = str_parms_create_str(keys);
2059 char *str;
2060 char value[256];
2061 struct str_parms *reply = str_parms_create();
2062 size_t i, j;
2063 int ret;
2064 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002065
2066 if (!query || !reply) {
2067 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2068 return NULL;
2069 }
2070
Eric Laurent994a6932013-07-17 11:51:42 -07002071 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2073 if (ret >= 0) {
2074 value[0] = '\0';
2075 i = 0;
2076 while (out->supported_channel_masks[i] != 0) {
2077 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2078 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2079 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002080 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002082 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083 first = false;
2084 break;
2085 }
2086 }
2087 i++;
2088 }
2089 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2090 str = str_parms_to_str(reply);
2091 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002092 voice_extn_out_get_parameters(out, query, reply);
2093 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002094 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002095 free(str);
2096 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002097 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002099
Alexy Joseph62142aa2015-11-16 15:10:34 -08002100
2101 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2102 if (ret >= 0) {
2103 value[0] = '\0';
2104 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2105 ALOGV("in direct_pcm");
2106 strlcat(value, "true", strlen("true"));
2107 } else {
2108 ALOGV("not in direct_pcm");
2109 strlcat(value, "false", strlen("false"));
2110 }
2111 str_parms_add_str(reply, "is_direct_pcm_track", value);
2112 str = str_parms_to_str(reply);
2113 }
2114
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002115 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2116 if (ret >= 0) {
2117 value[0] = '\0';
2118 i = 0;
2119 first = true;
2120 while (out->supported_formats[i] != 0) {
2121 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2122 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2123 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002124 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002125 }
2126 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2127 first = false;
2128 break;
2129 }
2130 }
2131 i++;
2132 }
2133 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2134 str = str_parms_to_str(reply);
2135 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 str_parms_destroy(query);
2137 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002138 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 return str;
2140}
2141
2142static uint32_t out_get_latency(const struct audio_stream_out *stream)
2143{
2144 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002145 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146
Alexy Josephaa54c872014-12-03 02:46:47 -08002147 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002148 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002149 } else {
2150 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002152 }
2153
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302154 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002155 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156}
2157
2158static int out_set_volume(struct audio_stream_out *stream, float left,
2159 float right)
2160{
Eric Laurenta9024de2013-04-04 09:19:12 -07002161 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 int volume[2];
2163
Eric Laurenta9024de2013-04-04 09:19:12 -07002164 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2165 /* only take left channel into account: the API is for stereo anyway */
2166 out->muted = (left == 0.0f);
2167 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002168 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002169 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2170 /*
2171 * Set mute or umute on HDMI passthrough stream.
2172 * Only take left channel into account.
2173 * Mute is 0 and unmute 1
2174 */
2175 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2176 } else {
2177 char mixer_ctl_name[128];
2178 struct audio_device *adev = out->dev;
2179 struct mixer_ctl *ctl;
2180 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002181 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002183 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2184 "Compress Playback %d Volume", pcm_device_id);
2185 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2186 if (!ctl) {
2187 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2188 __func__, mixer_ctl_name);
2189 return -EINVAL;
2190 }
2191 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2192 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2193 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2194 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002195 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002196 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 return -ENOSYS;
2199}
2200
2201static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2202 size_t bytes)
2203{
2204 struct stream_out *out = (struct stream_out *)stream;
2205 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302206 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002207 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002209 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302210
Naresh Tanniru80659832014-06-04 18:17:56 +05302211 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002212 // increase written size during SSR to avoid mismatch
2213 // with the written frames count in AF
2214 if (!is_offload_usecase(out->usecase))
2215 out->written += bytes / (out->config.channels * sizeof(short));
2216
Naresh Tanniru80659832014-06-04 18:17:56 +05302217 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302218 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302219 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302220 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002221 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 //during SSR for compress usecase we should return error to flinger
2223 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2224 pthread_mutex_unlock(&out->lock);
2225 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302226 }
2227 }
2228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002230 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002231 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002232 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2233 ret = voice_extn_compress_voip_start_output_stream(out);
2234 else
2235 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002236 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002239 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 goto exit;
2241 }
vivek mehta446c3962015-09-14 10:57:35 -07002242 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002243 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Ashish Jain81eb2a82015-05-13 10:52:34 +05302246 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2247 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2248 adev->is_channel_status_set = true;
2249 }
2250
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002251 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002252 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002253 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002254 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002255 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2256 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302257 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2258 ALOGD("copl(%p):send next track params in gapless", out);
2259 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2260 out->send_next_track_params = false;
2261 out->is_compr_metadata_avail = false;
2262 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002263 }
2264
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302266 if (ret < 0)
2267 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002268 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002269 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302270 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302272 } else if (-ENETRESET == ret) {
2273 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2274 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2275 pthread_mutex_unlock(&out->lock);
2276 out_standby(&out->stream.common);
2277 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002278 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302279 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002281 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 out->playback_started = 1;
2283 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002284
2285 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2286 popcount(out->channel_mask),
2287 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 }
2289 pthread_mutex_unlock(&out->lock);
2290 return ret;
2291 } else {
2292 if (out->pcm) {
2293 if (out->muted)
2294 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002295
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002297
2298 if (adev->adm_request_focus)
2299 adev->adm_request_focus(adev->adm_data, out->handle);
2300
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002301 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2302 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2303 else
2304 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002305
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302306 if (ret < 0)
2307 ret = -errno;
2308 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002309 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002310
2311 if (adev->adm_abandon_focus)
2312 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 }
2315
2316exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302317 /* ToDo: There may be a corner case when SSR happens back to back during
2318 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302319 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302320 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302321 }
2322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323 pthread_mutex_unlock(&out->lock);
2324
2325 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002326 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002327 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302328 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302329 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302330 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302331 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302332 out->standby = true;
2333 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002335 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302336 out_get_sample_rate(&out->stream.common));
2337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 }
2339 return bytes;
2340}
2341
2342static int out_get_render_position(const struct audio_stream_out *stream,
2343 uint32_t *dsp_frames)
2344{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302346 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002347
2348 if (dsp_frames == NULL)
2349 return -EINVAL;
2350
2351 *dsp_frames = 0;
2352 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002353 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002354 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302356 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302358 if (ret < 0)
2359 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 ALOGVV("%s rendered frames %d sample_rate %d",
2361 __func__, *dsp_frames, out->sample_rate);
2362 }
2363 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302364 if (-ENETRESET == ret) {
2365 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2366 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2367 return -EINVAL;
2368 } else if(ret < 0) {
2369 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2370 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302371 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2372 /*
2373 * Handle corner case where compress session is closed during SSR
2374 * and timestamp is queried
2375 */
2376 ALOGE(" ERROR: sound card not active, return error");
2377 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302378 } else {
2379 return 0;
2380 }
Zhou Song32a556e2015-05-05 10:46:56 +08002381 } else if (audio_is_linear_pcm(out->format)) {
2382 *dsp_frames = out->written;
2383 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 } else
2385 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386}
2387
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002388static int out_add_audio_effect(const struct audio_stream *stream __unused,
2389 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390{
2391 return 0;
2392}
2393
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002394static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2395 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396{
2397 return 0;
2398}
2399
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002400static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2401 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402{
2403 return -EINVAL;
2404}
2405
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002406static int out_get_presentation_position(const struct audio_stream_out *stream,
2407 uint64_t *frames, struct timespec *timestamp)
2408{
2409 struct stream_out *out = (struct stream_out *)stream;
2410 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002411 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002412
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002413 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002414
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002415 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002416 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302417 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002418 &out->sample_rate);
2419 ALOGVV("%s rendered frames %ld sample_rate %d",
2420 __func__, dsp_frames, out->sample_rate);
2421 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302422 if (ret < 0)
2423 ret = -errno;
2424 if (-ENETRESET == ret) {
2425 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2426 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2427 ret = -EINVAL;
2428 } else
2429 ret = 0;
2430
Eric Laurent949a0892013-09-20 09:20:13 -07002431 /* this is the best we can do */
2432 clock_gettime(CLOCK_MONOTONIC, timestamp);
2433 }
2434 } else {
2435 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002436 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002437 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2438 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002439 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002440 // This adjustment accounts for buffering after app processor.
2441 // It is based on estimated DSP latency per use case, rather than exact.
2442 signed_frames -=
2443 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2444
Eric Laurent949a0892013-09-20 09:20:13 -07002445 // It would be unusual for this value to be negative, but check just in case ...
2446 if (signed_frames >= 0) {
2447 *frames = signed_frames;
2448 ret = 0;
2449 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002450 }
2451 }
2452 }
2453
2454 pthread_mutex_unlock(&out->lock);
2455
2456 return ret;
2457}
2458
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459static int out_set_callback(struct audio_stream_out *stream,
2460 stream_callback_t callback, void *cookie)
2461{
2462 struct stream_out *out = (struct stream_out *)stream;
2463
2464 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 out->offload_callback = callback;
2467 out->offload_cookie = cookie;
2468 pthread_mutex_unlock(&out->lock);
2469 return 0;
2470}
2471
2472static int out_pause(struct audio_stream_out* stream)
2473{
2474 struct stream_out *out = (struct stream_out *)stream;
2475 int status = -ENOSYS;
2476 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002477 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002478 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002479 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302481 struct audio_device *adev = out->dev;
2482 int snd_scard_state = get_snd_card_state(adev);
2483
2484 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2485 status = compress_pause(out->compr);
2486
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002488
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302489 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002490 audio_extn_dts_notify_playback_state(out->usecase, 0,
2491 out->sample_rate, popcount(out->channel_mask),
2492 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002493 }
2494 pthread_mutex_unlock(&out->lock);
2495 }
2496 return status;
2497}
2498
2499static int out_resume(struct audio_stream_out* stream)
2500{
2501 struct stream_out *out = (struct stream_out *)stream;
2502 int status = -ENOSYS;
2503 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002504 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002505 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002507 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002508 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302509 struct audio_device *adev = out->dev;
2510 int snd_scard_state = get_snd_card_state(adev);
2511
2512 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2513 status = compress_resume(out->compr);
2514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002516
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302517 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002518 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2519 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002520 }
2521 pthread_mutex_unlock(&out->lock);
2522 }
2523 return status;
2524}
2525
2526static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2527{
2528 struct stream_out *out = (struct stream_out *)stream;
2529 int status = -ENOSYS;
2530 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002531 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002532 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2534 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2535 else
2536 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2537 pthread_mutex_unlock(&out->lock);
2538 }
2539 return status;
2540}
2541
2542static int out_flush(struct audio_stream_out* stream)
2543{
2544 struct stream_out *out = (struct stream_out *)stream;
2545 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002546 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002547 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002548 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002549 stop_compressed_output_l(out);
2550 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002551 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 return 0;
2553 }
2554 return -ENOSYS;
2555}
2556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557/** audio_stream_in implementation **/
2558static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2559{
2560 struct stream_in *in = (struct stream_in *)stream;
2561
2562 return in->config.rate;
2563}
2564
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002565static int in_set_sample_rate(struct audio_stream *stream __unused,
2566 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567{
2568 return -ENOSYS;
2569}
2570
2571static size_t in_get_buffer_size(const struct audio_stream *stream)
2572{
2573 struct stream_in *in = (struct stream_in *)stream;
2574
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002575 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2576 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002577 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2578 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002579
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002580 return in->config.period_size *
2581 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582}
2583
2584static uint32_t in_get_channels(const struct audio_stream *stream)
2585{
2586 struct stream_in *in = (struct stream_in *)stream;
2587
2588 return in->channel_mask;
2589}
2590
2591static audio_format_t in_get_format(const struct audio_stream *stream)
2592{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002593 struct stream_in *in = (struct stream_in *)stream;
2594
2595 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596}
2597
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002598static int in_set_format(struct audio_stream *stream __unused,
2599 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600{
2601 return -ENOSYS;
2602}
2603
2604static int in_standby(struct audio_stream *stream)
2605{
2606 struct stream_in *in = (struct stream_in *)stream;
2607 struct audio_device *adev = in->dev;
2608 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302609 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2610 stream, in->usecase, use_case_table[in->usecase]);
2611
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002612 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2613 /* Ignore standby in case of voip call because the voip input
2614 * stream is closed in adev_close_input_stream()
2615 */
2616 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2617 return status;
2618 }
2619
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002620 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002621 if (!in->standby && in->is_st_session) {
2622 ALOGD("%s: sound trigger pcm stop lab", __func__);
2623 audio_extn_sound_trigger_stop_lab(in);
2624 in->standby = 1;
2625 }
2626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002628 if (adev->adm_deregister_stream)
2629 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2630
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002631 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002633 if (in->pcm) {
2634 pcm_close(in->pcm);
2635 in->pcm = NULL;
2636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002638 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 }
2640 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002641 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 return status;
2643}
2644
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002645static int in_dump(const struct audio_stream *stream __unused,
2646 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647{
2648 return 0;
2649}
2650
2651static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2652{
2653 struct stream_in *in = (struct stream_in *)stream;
2654 struct audio_device *adev = in->dev;
2655 struct str_parms *parms;
2656 char *str;
2657 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002658 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302660 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 parms = str_parms_create_str(kvpairs);
2662
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302663 if (!parms)
2664 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002665 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002666 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002667
2668 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2669 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 val = atoi(value);
2671 /* no audio source uses val == 0 */
2672 if ((in->source != val) && (val != 0)) {
2673 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002674 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2675 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2676 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2677 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002678 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002679 err = voice_extn_compress_voip_open_input_stream(in);
2680 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002681 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002682 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002683 }
2684 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
2686 }
2687
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002688 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2689 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002691 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 in->device = val;
2693 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002694 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002695 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 }
2697 }
2698
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002699done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002701 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702
2703 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302704error:
Eric Laurent994a6932013-07-17 11:51:42 -07002705 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 return ret;
2707}
2708
2709static char* in_get_parameters(const struct audio_stream *stream,
2710 const char *keys)
2711{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002712 struct stream_in *in = (struct stream_in *)stream;
2713 struct str_parms *query = str_parms_create_str(keys);
2714 char *str;
2715 char value[256];
2716 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002717
2718 if (!query || !reply) {
2719 ALOGE("in_get_parameters: failed to create query or reply");
2720 return NULL;
2721 }
2722
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002723 ALOGV("%s: enter: keys - %s", __func__, keys);
2724
2725 voice_extn_in_get_parameters(in, query, reply);
2726
2727 str = str_parms_to_str(reply);
2728 str_parms_destroy(query);
2729 str_parms_destroy(reply);
2730
2731 ALOGV("%s: exit: returns - %s", __func__, str);
2732 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733}
2734
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002735static int in_set_gain(struct audio_stream_in *stream __unused,
2736 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737{
2738 return 0;
2739}
2740
2741static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2742 size_t bytes)
2743{
2744 struct stream_in *in = (struct stream_in *)stream;
2745 struct audio_device *adev = in->dev;
2746 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302747 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002749 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302750
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002751 if (in->is_st_session) {
2752 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2753 /* Read from sound trigger HAL */
2754 audio_extn_sound_trigger_read(in, buffer, bytes);
2755 pthread_mutex_unlock(&in->lock);
2756 return bytes;
2757 }
2758
2759 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2760 ALOGD(" %s: sound card is not active/SSR state", __func__);
2761 ret= -EIO;;
2762 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302763 }
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002766 pthread_mutex_lock(&adev->lock);
2767 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2768 ret = voice_extn_compress_voip_start_input_stream(in);
2769 else
2770 ret = start_input_stream(in);
2771 pthread_mutex_unlock(&adev->lock);
2772 if (ret != 0) {
2773 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 }
2775 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002776 if (adev->adm_register_input_stream)
2777 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002780 if (adev->adm_request_focus)
2781 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002784 if (audio_extn_ssr_get_enabled() &&
2785 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002786 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002787 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2788 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002789 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2790 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002791 else
2792 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302793 if (ret < 0)
2794 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 }
2796
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002797 if (adev->adm_abandon_focus)
2798 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 /*
2801 * Instead of writing zeroes here, we could trust the hardware
2802 * to always provide zeroes when muted.
2803 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302804 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2805 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 memset(buffer, 0, bytes);
2807
2808exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302809 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302810 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002811 if (-ENETRESET == ret)
2812 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 pthread_mutex_unlock(&in->lock);
2815
2816 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302817 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302818 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302819 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302820 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302821 in->standby = true;
2822 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302823 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002825 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002826 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302827 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 }
2829 return bytes;
2830}
2831
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002832static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833{
2834 return 0;
2835}
2836
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002837static int add_remove_audio_effect(const struct audio_stream *stream,
2838 effect_handle_t effect,
2839 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002841 struct stream_in *in = (struct stream_in *)stream;
2842 int status = 0;
2843 effect_descriptor_t desc;
2844
2845 status = (*effect)->get_descriptor(effect, &desc);
2846 if (status != 0)
2847 return status;
2848
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002849 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002850 pthread_mutex_lock(&in->dev->lock);
2851 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2852 in->enable_aec != enable &&
2853 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2854 in->enable_aec = enable;
2855 if (!in->standby)
2856 select_devices(in->dev, in->usecase);
2857 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002858 if (in->enable_ns != enable &&
2859 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2860 in->enable_ns = enable;
2861 if (!in->standby)
2862 select_devices(in->dev, in->usecase);
2863 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002864 pthread_mutex_unlock(&in->dev->lock);
2865 pthread_mutex_unlock(&in->lock);
2866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 return 0;
2868}
2869
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002870static int in_add_audio_effect(const struct audio_stream *stream,
2871 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872{
Eric Laurent994a6932013-07-17 11:51:42 -07002873 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002874 return add_remove_audio_effect(stream, effect, true);
2875}
2876
2877static int in_remove_audio_effect(const struct audio_stream *stream,
2878 effect_handle_t effect)
2879{
Eric Laurent994a6932013-07-17 11:51:42 -07002880 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002881 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882}
2883
2884static int adev_open_output_stream(struct audio_hw_device *dev,
2885 audio_io_handle_t handle,
2886 audio_devices_t devices,
2887 audio_output_flags_t flags,
2888 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002889 struct audio_stream_out **stream_out,
2890 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891{
2892 struct audio_device *adev = (struct audio_device *)dev;
2893 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002894 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002895 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302898
2899 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2900 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002901 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302902 return -EINVAL;
2903 }
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2906
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302907 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2908 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2909 devices, flags, &out->stream);
2910
2911
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002912 if (!out) {
2913 return -ENOMEM;
2914 }
2915
Haynes Mathew George204045b2015-02-25 20:32:03 -08002916 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002917 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002918 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 if (devices == AUDIO_DEVICE_NONE)
2921 devices = AUDIO_DEVICE_OUT_SPEAKER;
2922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 out->flags = flags;
2924 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002925 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002926 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 out->sample_rate = config->sample_rate;
2928 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2929 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002930 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002931 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002932 out->non_blocking = 0;
2933 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934
2935 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002936 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2937 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002938 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2939 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2940
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002941 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002942 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2943 ret = read_hdmi_channel_masks(out);
2944
2945 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2946 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002947 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002948 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002949 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002950
2951 if (config->sample_rate == 0)
2952 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2953 if (config->channel_mask == 0)
2954 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2955
2956 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002958 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2959 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002961 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002963 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2964 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002965 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002966 ret = voice_extn_compress_voip_open_output_stream(out);
2967 if (ret != 0) {
2968 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2969 __func__, ret);
2970 goto error_open;
2971 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002972 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2973 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002975 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2976 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2977 ALOGE("%s: Unsupported Offload information", __func__);
2978 ret = -EINVAL;
2979 goto error_open;
2980 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002981
2982 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2983 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2984 ALOGV("read and update_pass through formats");
2985 ret = audio_extn_dolby_update_passt_formats(adev, out);
2986 if(ret != 0) {
2987 goto error_open;
2988 }
2989 if(config->offload_info.format == 0)
2990 config->offload_info.format = out->supported_formats[0];
2991 }
2992
Mingming Yin90310102013-11-13 16:57:00 -08002993 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002994 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002995 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 ret = -EINVAL;
2997 goto error_open;
2998 }
2999
3000 out->compr_config.codec = (struct snd_codec *)
3001 calloc(1, sizeof(struct snd_codec));
3002
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003003 if (!out->compr_config.codec) {
3004 ret = -ENOMEM;
3005 goto error_open;
3006 }
3007
vivek mehta0ea887a2015-08-26 14:01:20 -07003008 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003009 out->usecase = get_offload_usecase(adev, true);
3010 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003011 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003012 out->stream.set_callback = out_set_callback;
3013 out->stream.pause = out_pause;
3014 out->stream.resume = out_resume;
3015 out->stream.drain = out_drain;
3016 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003017 out->usecase = get_offload_usecase(adev, false);
3018 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003019 }
vivek mehta446c3962015-09-14 10:57:35 -07003020
3021 if (out->usecase == USECASE_INVALID) {
3022 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3023 ret = -EEXIST;
3024 goto error_open;
3025 }
3026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027 if (config->offload_info.channel_mask)
3028 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003029 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003031 config->offload_info.channel_mask = config->channel_mask;
3032 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003033 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034 out->sample_rate = config->offload_info.sample_rate;
3035
Mingming Yin3ee55c62014-08-04 14:23:35 -07003036 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003038 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003039 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003040 audio_extn_dolby_get_snd_codec_id(adev, out,
3041 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003042 else
3043 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003045
3046 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3047 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003048 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003049 platform_get_pcm_offload_buffer_size(&config->offload_info);
3050 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3051 out->compr_config.fragment_size =
3052 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003053 } else {
3054 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003055 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003056 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3058 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003059 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 out->compr_config.codec->bit_rate =
3061 config->offload_info.bit_rate;
3062 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003063 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303065 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003066 /*TODO: Do we need to change it for passthrough */
3067 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068
Manish Dewangana6fc5442015-08-24 20:30:31 +05303069 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3070 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3071 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003073 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3074 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003075 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003076 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003077 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3078 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003079
Mingming Yin3ee55c62014-08-04 14:23:35 -07003080 if (out->bit_width == 24) {
3081 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3082 }
3083
Amit Shekhar6f461b12014-08-01 14:52:58 -07003084 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303085 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003086
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3088 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003089
Mingming Yin497419f2015-07-01 16:57:32 -07003090 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003091 //this flag is set from framework only if its for PCM formats
3092 //no need to check for PCM format again
3093 out->non_blocking = 0;
3094 out->use_small_bufs = true;
3095 ALOGI("Keep write blocking for small buff: non_blockling %d",
3096 out->non_blocking);
3097 }
3098
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003099 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303100 out->send_next_track_params = false;
3101 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003102 out->offload_state = OFFLOAD_STATE_IDLE;
3103 out->playback_started = 0;
3104
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003105 audio_extn_dts_create_state_notifier_node(out->usecase);
3106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 create_offload_callback_thread(out);
3108 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3109 __func__, config->offload_info.version,
3110 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003111 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003112 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003113 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3114 ret = voice_check_and_set_incall_music_usecase(adev, out);
3115 if (ret != 0) {
3116 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3117 __func__, ret);
3118 goto error_open;
3119 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003120 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3121 if (config->sample_rate == 0)
3122 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3123 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3124 config->sample_rate != 8000) {
3125 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3126 ret = -EINVAL;
3127 goto error_open;
3128 }
3129 out->sample_rate = config->sample_rate;
3130 out->config.rate = config->sample_rate;
3131 if (config->format == AUDIO_FORMAT_DEFAULT)
3132 config->format = AUDIO_FORMAT_PCM_16_BIT;
3133 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3134 config->format = AUDIO_FORMAT_PCM_16_BIT;
3135 ret = -EINVAL;
3136 goto error_open;
3137 }
3138 out->format = config->format;
3139 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3140 out->config = pcm_config_afe_proxy_playback;
3141 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003142 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3143 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3144 out->config = pcm_config_low_latency;
3145 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003146 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003147 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3149 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003151 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3152 format = AUDIO_FORMAT_PCM_16_BIT;
3153 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3154 out->config = pcm_config_deep_buffer;
3155 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003156 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003157 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003158 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003159 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003160 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003161 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 }
3163
Amit Shekhar1d896042014-10-03 13:16:09 -07003164 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3165 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003166 /* TODO remove this hardcoding and check why width is zero*/
3167 if (out->bit_width == 0)
3168 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003169 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3170 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003171 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303172 out->bit_width, out->channel_mask,
3173 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003174 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3175 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3176 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003177 if(adev->primary_output == NULL)
3178 adev->primary_output = out;
3179 else {
3180 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003181 ret = -EEXIST;
3182 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003183 }
3184 }
3185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 /* Check if this usecase is already existing */
3187 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003188 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3189 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003192 ret = -EEXIST;
3193 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 }
3195 pthread_mutex_unlock(&adev->lock);
3196
3197 out->stream.common.get_sample_rate = out_get_sample_rate;
3198 out->stream.common.set_sample_rate = out_set_sample_rate;
3199 out->stream.common.get_buffer_size = out_get_buffer_size;
3200 out->stream.common.get_channels = out_get_channels;
3201 out->stream.common.get_format = out_get_format;
3202 out->stream.common.set_format = out_set_format;
3203 out->stream.common.standby = out_standby;
3204 out->stream.common.dump = out_dump;
3205 out->stream.common.set_parameters = out_set_parameters;
3206 out->stream.common.get_parameters = out_get_parameters;
3207 out->stream.common.add_audio_effect = out_add_audio_effect;
3208 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3209 out->stream.get_latency = out_get_latency;
3210 out->stream.set_volume = out_set_volume;
3211 out->stream.write = out_write;
3212 out->stream.get_render_position = out_get_render_position;
3213 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003214 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003217 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003218 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219
3220 config->format = out->stream.common.get_format(&out->stream.common);
3221 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3222 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3223
3224 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303225 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003226 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003227
3228 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3229 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3230 popcount(out->channel_mask), out->playback_started);
3231
Eric Laurent994a6932013-07-17 11:51:42 -07003232 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003234
3235error_open:
3236 free(out);
3237 *stream_out = NULL;
3238 ALOGD("%s: exit: ret %d", __func__, ret);
3239 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240}
3241
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003242static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 struct audio_stream_out *stream)
3244{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003245 struct stream_out *out = (struct stream_out *)stream;
3246 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003247 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303249 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3250
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003251 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303252 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003253 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303254 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003255 if(ret != 0)
3256 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3257 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003258 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003259 out_standby(&stream->common);
3260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003261 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003262 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003264 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003265 if (out->compr_config.codec != NULL)
3266 free(out->compr_config.codec);
3267 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003268
3269 if (adev->voice_tx_output == out)
3270 adev->voice_tx_output = NULL;
3271
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 pthread_cond_destroy(&out->cond);
3273 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003275 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276}
3277
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003278static void close_compress_sessions(struct audio_device *adev)
3279{
Mingming Yin7b762e72015-03-04 13:47:32 -08003280 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303281 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003282 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003283 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303284
3285 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003286 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303287 if (is_offload_usecase(usecase->id)) {
3288 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003289 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3290 out = usecase->stream.out;
3291 pthread_mutex_unlock(&adev->lock);
3292 out_standby(&out->stream.common);
3293 pthread_mutex_lock(&adev->lock);
3294 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303295 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003296 }
3297 pthread_mutex_unlock(&adev->lock);
3298}
3299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3301{
3302 struct audio_device *adev = (struct audio_device *)dev;
3303 struct str_parms *parms;
3304 char *str;
3305 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003306 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003307 int ret;
3308 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003310 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303313 if (!parms)
3314 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003315 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3316 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303317 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303318 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303319 struct listnode *node;
3320 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303321 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303322 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003323 //close compress sessions on OFFLINE status
3324 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303325 } else if (strstr(snd_card_status, "ONLINE")) {
3326 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303327 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003328 //send dts hpx license if enabled
3329 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303330 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303331 }
3332
3333 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003334 status = voice_set_parameters(adev, parms);
3335 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003336 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003338 status = platform_set_parameters(adev->platform, parms);
3339 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003340 goto done;
3341
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003342 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3343 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003344 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3346 adev->bluetooth_nrec = true;
3347 else
3348 adev->bluetooth_nrec = false;
3349 }
3350
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003351 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3352 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3354 adev->screen_off = false;
3355 else
3356 adev->screen_off = true;
3357 }
3358
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003359 ret = str_parms_get_int(parms, "rotation", &val);
3360 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003361 bool reverse_speakers = false;
3362 switch(val) {
3363 // FIXME: note that the code below assumes that the speakers are in the correct placement
3364 // relative to the user when the device is rotated 90deg from its default rotation. This
3365 // assumption is device-specific, not platform-specific like this code.
3366 case 270:
3367 reverse_speakers = true;
3368 break;
3369 case 0:
3370 case 90:
3371 case 180:
3372 break;
3373 default:
3374 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003375 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003376 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003377 if (status == 0) {
3378 if (adev->speaker_lr_swap != reverse_speakers) {
3379 adev->speaker_lr_swap = reverse_speakers;
3380 // only update the selected device if there is active pcm playback
3381 struct audio_usecase *usecase;
3382 struct listnode *node;
3383 list_for_each(node, &adev->usecase_list) {
3384 usecase = node_to_item(node, struct audio_usecase, list);
3385 if (usecase->type == PCM_PLAYBACK) {
3386 select_devices(adev, usecase->id);
3387 break;
3388 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003389 }
3390 }
3391 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003392 }
3393
Mingming Yin514a8bc2014-07-29 15:22:21 -07003394 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3395 if (ret >= 0) {
3396 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3397 adev->bt_wb_speech_enabled = true;
3398 else
3399 adev->bt_wb_speech_enabled = false;
3400 }
3401
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003402 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3403 if (ret >= 0) {
3404 val = atoi(value);
3405 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3406 ALOGV("cache new edid");
3407 platform_cache_edid(adev->platform);
3408 }
3409 }
3410
3411 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3412 if (ret >= 0) {
3413 val = atoi(value);
3414 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3415 ALOGV("invalidate cached edid");
3416 platform_invalidate_edid(adev->platform);
3417 }
3418 }
3419
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003420 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003421
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003422done:
3423 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003424 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303425error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003426 ALOGV("%s: exit with code(%d)", __func__, status);
3427 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428}
3429
3430static char* adev_get_parameters(const struct audio_hw_device *dev,
3431 const char *keys)
3432{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003433 struct audio_device *adev = (struct audio_device *)dev;
3434 struct str_parms *reply = str_parms_create();
3435 struct str_parms *query = str_parms_create_str(keys);
3436 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303437 char value[256] = {0};
3438 int ret = 0;
3439
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003440 if (!query || !reply) {
3441 ALOGE("adev_get_parameters: failed to create query or reply");
3442 return NULL;
3443 }
3444
Naresh Tannirud7205b62014-06-20 02:54:48 +05303445 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3446 sizeof(value));
3447 if (ret >=0) {
3448 int val = 1;
3449 pthread_mutex_lock(&adev->snd_card_status.lock);
3450 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3451 val = 0;
3452 pthread_mutex_unlock(&adev->snd_card_status.lock);
3453 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3454 goto exit;
3455 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003456
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003457 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003458 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003459 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003460 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303461 pthread_mutex_unlock(&adev->lock);
3462
Naresh Tannirud7205b62014-06-20 02:54:48 +05303463exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003464 str = str_parms_to_str(reply);
3465 str_parms_destroy(query);
3466 str_parms_destroy(reply);
3467
3468 ALOGV("%s: exit: returns - %s", __func__, str);
3469 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470}
3471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003472static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473{
3474 return 0;
3475}
3476
3477static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3478{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003479 int ret;
3480 struct audio_device *adev = (struct audio_device *)dev;
3481 pthread_mutex_lock(&adev->lock);
3482 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003483 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003484 pthread_mutex_unlock(&adev->lock);
3485 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486}
3487
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003488static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3489 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490{
3491 return -ENOSYS;
3492}
3493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003494static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3495 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496{
3497 return -ENOSYS;
3498}
3499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003500static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3501 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502{
3503 return -ENOSYS;
3504}
3505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003506static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3507 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508{
3509 return -ENOSYS;
3510}
3511
3512static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3513{
3514 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 pthread_mutex_lock(&adev->lock);
3517 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003518 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003520 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3521 voice_is_in_call(adev)) {
3522 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003523 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003524 adev->current_call_output = NULL;
3525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 }
3527 pthread_mutex_unlock(&adev->lock);
3528 return 0;
3529}
3530
3531static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3532{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003533 int ret;
3534
3535 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003536 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003537 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3538 pthread_mutex_unlock(&adev->lock);
3539
3540 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541}
3542
3543static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3544{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003545 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 return 0;
3547}
3548
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003549static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 const struct audio_config *config)
3551{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003552 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003554 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3555 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556}
3557
3558static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003559 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 audio_devices_t devices,
3561 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003562 struct audio_stream_in **stream_in,
3563 audio_input_flags_t flags __unused,
3564 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003565 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566{
3567 struct audio_device *adev = (struct audio_device *)dev;
3568 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003569 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003570 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003571 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573 *stream_in = NULL;
3574 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3575 return -EINVAL;
3576
3577 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003578
3579 if (!in) {
3580 ALOGE("failed to allocate input stream");
3581 return -ENOMEM;
3582 }
3583
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303584 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003585 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3586 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003588 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003589 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 in->stream.common.get_sample_rate = in_get_sample_rate;
3592 in->stream.common.set_sample_rate = in_set_sample_rate;
3593 in->stream.common.get_buffer_size = in_get_buffer_size;
3594 in->stream.common.get_channels = in_get_channels;
3595 in->stream.common.get_format = in_get_format;
3596 in->stream.common.set_format = in_set_format;
3597 in->stream.common.standby = in_standby;
3598 in->stream.common.dump = in_dump;
3599 in->stream.common.set_parameters = in_set_parameters;
3600 in->stream.common.get_parameters = in_get_parameters;
3601 in->stream.common.add_audio_effect = in_add_audio_effect;
3602 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3603 in->stream.set_gain = in_set_gain;
3604 in->stream.read = in_read;
3605 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3606
3607 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003608 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 in->standby = 1;
3611 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003612 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003613 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614
3615 /* Update config params with the requested sample rate and channels */
3616 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003617 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3618 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3619 is_low_latency = true;
3620#if LOW_LATENCY_CAPTURE_USE_CASE
3621 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3622#endif
3623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003626 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003628 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303629 if (adev->mode != AUDIO_MODE_IN_CALL) {
3630 ret = -EINVAL;
3631 goto err_open;
3632 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003633 if (config->sample_rate == 0)
3634 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3635 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3636 config->sample_rate != 8000) {
3637 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3638 ret = -EINVAL;
3639 goto err_open;
3640 }
3641 if (config->format == AUDIO_FORMAT_DEFAULT)
3642 config->format = AUDIO_FORMAT_PCM_16_BIT;
3643 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3644 config->format = AUDIO_FORMAT_PCM_16_BIT;
3645 ret = -EINVAL;
3646 goto err_open;
3647 }
3648
3649 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3650 in->config = pcm_config_afe_proxy_record;
3651 in->config.channels = channel_count;
3652 in->config.rate = config->sample_rate;
3653 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003654 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003655 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003656 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3657 ret = -EINVAL;
3658 goto err_open;
3659 }
3660 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003661 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003662 }
Mingming Yine62d7842013-10-25 16:26:03 -07003663 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003664 audio_extn_compr_cap_format_supported(config->format) &&
3665 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003666 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003667 } else {
3668 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003669 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003670 buffer_size = get_input_buffer_size(config->sample_rate,
3671 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003672 channel_count,
3673 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003674 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003675 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3676 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3677 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3678 (in->config.rate == 8000 || in->config.rate == 16000) &&
3679 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3680 voice_extn_compress_voip_open_input_stream(in);
3681 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003682 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003684 /* This stream could be for sound trigger lab,
3685 get sound trigger pcm if present */
3686 audio_extn_sound_trigger_check_and_get_session(in);
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003689 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003690 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
3692err_open:
3693 free(in);
3694 *stream_in = NULL;
3695 return ret;
3696}
3697
3698static void adev_close_input_stream(struct audio_hw_device *dev,
3699 struct audio_stream_in *stream)
3700{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003701 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003702 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003703 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303704
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303705 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003706
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303707 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003708 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303709
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003710 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303711 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003712 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303713 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003714 if (ret != 0)
3715 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3716 __func__, ret);
3717 } else
3718 in_standby(&stream->common);
3719
Mingming Yin7b762e72015-03-04 13:47:32 -08003720 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003721 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003722 audio_extn_ssr_deinit();
3723 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724
Mingming Yine62d7842013-10-25 16:26:03 -07003725 if(audio_extn_compr_cap_enabled() &&
3726 audio_extn_compr_cap_format_supported(in->config.format))
3727 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003728
3729 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 return;
3731}
3732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003733static int adev_dump(const audio_hw_device_t *device __unused,
3734 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735{
3736 return 0;
3737}
3738
3739static int adev_close(hw_device_t *device)
3740{
3741 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003742
3743 if (!adev)
3744 return 0;
3745
3746 pthread_mutex_lock(&adev_init_lock);
3747
3748 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003749 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003750 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003751 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003752 audio_route_free(adev->audio_route);
3753 free(adev->snd_dev_ref_cnt);
3754 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003755 if (adev->adm_deinit)
3756 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003757 free(device);
3758 adev = NULL;
3759 }
3760 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 return 0;
3763}
3764
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003765/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3766 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3767 * just that it _might_ work.
3768 */
3769static int period_size_is_plausible_for_low_latency(int period_size)
3770{
3771 switch (period_size) {
3772 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003773 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003774 case 240:
3775 case 320:
3776 case 480:
3777 return 1;
3778 default:
3779 return 0;
3780 }
3781}
3782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783static int adev_open(const hw_module_t *module, const char *name,
3784 hw_device_t **device)
3785{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003786 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003788 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3790
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003791 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003792 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003793 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003794 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003795 ALOGD("%s: returning existing instance of adev", __func__);
3796 ALOGD("%s: exit", __func__);
3797 pthread_mutex_unlock(&adev_init_lock);
3798 return 0;
3799 }
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 adev = calloc(1, sizeof(struct audio_device));
3802
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003803 if (!adev) {
3804 pthread_mutex_unlock(&adev_init_lock);
3805 return -ENOMEM;
3806 }
3807
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003808 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3811 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3812 adev->device.common.module = (struct hw_module_t *)module;
3813 adev->device.common.close = adev_close;
3814
3815 adev->device.init_check = adev_init_check;
3816 adev->device.set_voice_volume = adev_set_voice_volume;
3817 adev->device.set_master_volume = adev_set_master_volume;
3818 adev->device.get_master_volume = adev_get_master_volume;
3819 adev->device.set_master_mute = adev_set_master_mute;
3820 adev->device.get_master_mute = adev_get_master_mute;
3821 adev->device.set_mode = adev_set_mode;
3822 adev->device.set_mic_mute = adev_set_mic_mute;
3823 adev->device.get_mic_mute = adev_get_mic_mute;
3824 adev->device.set_parameters = adev_set_parameters;
3825 adev->device.get_parameters = adev_get_parameters;
3826 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3827 adev->device.open_output_stream = adev_open_output_stream;
3828 adev->device.close_output_stream = adev_close_output_stream;
3829 adev->device.open_input_stream = adev_open_input_stream;
3830 adev->device.close_input_stream = adev_close_input_stream;
3831 adev->device.dump = adev_dump;
3832
3833 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003835 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003836 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003839 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003840 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003841 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003842 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003843 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003844 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003845 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303846 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303847 adev->perf_lock_opts[0] = 0x101;
3848 adev->perf_lock_opts[1] = 0x20E;
3849 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303850
3851 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3852 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003854 adev->platform = platform_init(adev);
3855 if (!adev->platform) {
3856 free(adev->snd_dev_ref_cnt);
3857 free(adev);
3858 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3859 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003860 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003861 return -EINVAL;
3862 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003863
Naresh Tanniru4c630392014-05-12 01:05:52 +05303864 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3865
Eric Laurentc4aef752013-09-12 17:45:53 -07003866 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3867 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3868 if (adev->visualizer_lib == NULL) {
3869 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3870 } else {
3871 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3872 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003873 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003874 "visualizer_hal_start_output");
3875 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003876 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003877 "visualizer_hal_stop_output");
3878 }
3879 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003880 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003881 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003882
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003883 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3884 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3885 if (adev->offload_effects_lib == NULL) {
3886 ALOGE("%s: DLOPEN failed for %s", __func__,
3887 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3888 } else {
3889 ALOGV("%s: DLOPEN successful for %s", __func__,
3890 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3891 adev->offload_effects_start_output =
3892 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3893 "offload_effects_bundle_hal_start_output");
3894 adev->offload_effects_stop_output =
3895 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3896 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003897 adev->offload_effects_set_hpx_state =
3898 (int (*)(bool))dlsym(adev->offload_effects_lib,
3899 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303900 adev->offload_effects_get_parameters =
3901 (void (*)(struct str_parms *, struct str_parms *))
3902 dlsym(adev->offload_effects_lib,
3903 "offload_effects_bundle_get_parameters");
3904 adev->offload_effects_set_parameters =
3905 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3906 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003907 }
3908 }
3909
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003910 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3911 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3912 if (adev->adm_lib == NULL) {
3913 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3914 } else {
3915 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3916 adev->adm_init = (adm_init_t)
3917 dlsym(adev->adm_lib, "adm_init");
3918 adev->adm_deinit = (adm_deinit_t)
3919 dlsym(adev->adm_lib, "adm_deinit");
3920 adev->adm_register_input_stream = (adm_register_input_stream_t)
3921 dlsym(adev->adm_lib, "adm_register_input_stream");
3922 adev->adm_register_output_stream = (adm_register_output_stream_t)
3923 dlsym(adev->adm_lib, "adm_register_output_stream");
3924 adev->adm_deregister_stream = (adm_deregister_stream_t)
3925 dlsym(adev->adm_lib, "adm_deregister_stream");
3926 adev->adm_request_focus = (adm_request_focus_t)
3927 dlsym(adev->adm_lib, "adm_request_focus");
3928 adev->adm_abandon_focus = (adm_abandon_focus_t)
3929 dlsym(adev->adm_lib, "adm_abandon_focus");
3930 }
3931 }
3932
Mingming Yin514a8bc2014-07-29 15:22:21 -07003933 adev->bt_wb_speech_enabled = false;
3934
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003935 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 *device = &adev->device.common;
3937
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003938 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3939 &adev->streams_output_cfg_list);
3940
Kiran Kandi910e1862013-10-29 13:29:42 -07003941 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003942
3943 char value[PROPERTY_VALUE_MAX];
3944 int trial;
3945 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3946 trial = atoi(value);
3947 if (period_size_is_plausible_for_low_latency(trial)) {
3948 pcm_config_low_latency.period_size = trial;
3949 pcm_config_low_latency.start_threshold = trial / 4;
3950 pcm_config_low_latency.avail_min = trial / 4;
3951 configured_low_latency_capture_period_size = trial;
3952 }
3953 }
3954 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3955 trial = atoi(value);
3956 if (period_size_is_plausible_for_low_latency(trial)) {
3957 configured_low_latency_capture_period_size = trial;
3958 }
3959 }
3960
vivek mehta446c3962015-09-14 10:57:35 -07003961 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003962 pthread_mutex_unlock(&adev_init_lock);
3963
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003964 if (adev->adm_init)
3965 adev->adm_data = adev->adm_init();
3966
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303967 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07003968 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 return 0;
3970}
3971
3972static struct hw_module_methods_t hal_module_methods = {
3973 .open = adev_open,
3974};
3975
3976struct audio_module HAL_MODULE_INFO_SYM = {
3977 .common = {
3978 .tag = HARDWARE_MODULE_TAG,
3979 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3980 .hal_api_version = HARDWARE_HAL_API_VERSION,
3981 .id = AUDIO_HARDWARE_MODULE_ID,
3982 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003983 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 .methods = &hal_module_methods,
3985 },
3986};