blob: 5500ee34e1799fe31957522e87c516b1ef84ee75 [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
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07001060 if (audio_extn_ssr_get_stream() == in) {
1061 audio_extn_ssr_deinit();
1062 }
1063
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001064 list_remove(&uc_info->list);
1065 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066
Eric Laurent994a6932013-07-17 11:51:42 -07001067 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 return ret;
1069}
1070
1071int start_input_stream(struct stream_in *in)
1072{
1073 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001074 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 struct audio_usecase *uc_info;
1076 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301077 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078
Mingming Yin2664a5b2015-09-03 10:53:11 -07001079 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1080 if (get_usecase_from_list(adev, usecase) == NULL)
1081 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301082 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1083 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001084
Naresh Tanniru80659832014-06-04 18:17:56 +05301085
1086 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301087 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301088 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301089 goto error_config;
1090 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301091
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001092 /* Check if source matches incall recording usecase criteria */
1093 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1094 if (ret)
1095 goto error_config;
1096 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001097 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1098
1099 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1100 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1101 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1102 goto error_config;
1103 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001104
Eric Laurentb23d5282013-05-14 15:27:20 -07001105 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106 if (in->pcm_device_id < 0) {
1107 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1108 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001109 ret = -EINVAL;
1110 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112
1113 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001115
1116 if (!uc_info) {
1117 ret = -ENOMEM;
1118 goto error_config;
1119 }
1120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 uc_info->id = in->usecase;
1122 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001123 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 uc_info->devices = in->device;
1125 uc_info->in_snd_device = SND_DEVICE_NONE;
1126 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001128 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301129 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1130 adev->perf_lock_opts,
1131 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133
Eric Laurentc8400632013-02-14 19:04:54 -08001134 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001135 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1136
1137 unsigned int flags = PCM_IN;
1138 unsigned int pcm_open_retry_count = 0;
1139
1140 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1141 flags |= PCM_MMAP | PCM_NOIRQ;
1142 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1143 }
1144
1145 while (1) {
1146 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1147 flags, &in->config);
1148 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1149 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1150 if (in->pcm != NULL) {
1151 pcm_close(in->pcm);
1152 in->pcm = NULL;
1153 }
1154 if (pcm_open_retry_count-- == 0) {
1155 ret = -EIO;
1156 goto error_open;
1157 }
1158 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1159 continue;
1160 }
1161 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001163
1164 ALOGV("%s: pcm_prepare", __func__);
1165 ret = pcm_prepare(in->pcm);
1166 if (ret < 0) {
1167 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1168 pcm_close(in->pcm);
1169 in->pcm = NULL;
1170 goto error_open;
1171 }
1172
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301173 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001174 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001175
Eric Laurentc8400632013-02-14 19:04:54 -08001176 return ret;
1177
1178error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301179 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001180 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001181error_config:
1182 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301183 /*
1184 * sleep 50ms to allow sufficient time for kernel
1185 * drivers to recover incases like SSR.
1186 */
1187 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001189
1190 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191}
1192
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001193void lock_input_stream(struct stream_in *in)
1194{
1195 pthread_mutex_lock(&in->pre_lock);
1196 pthread_mutex_lock(&in->lock);
1197 pthread_mutex_unlock(&in->pre_lock);
1198}
1199
1200void lock_output_stream(struct stream_out *out)
1201{
1202 pthread_mutex_lock(&out->pre_lock);
1203 pthread_mutex_lock(&out->lock);
1204 pthread_mutex_unlock(&out->pre_lock);
1205}
1206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001207/* must be called with out->lock locked */
1208static int send_offload_cmd_l(struct stream_out* out, int command)
1209{
1210 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1211
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001212 if (!cmd) {
1213 ALOGE("failed to allocate mem for command 0x%x", command);
1214 return -ENOMEM;
1215 }
1216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 ALOGVV("%s %d", __func__, command);
1218
1219 cmd->cmd = command;
1220 list_add_tail(&out->offload_cmd_list, &cmd->node);
1221 pthread_cond_signal(&out->offload_cond);
1222 return 0;
1223}
1224
1225/* must be called iwth out->lock locked */
1226static void stop_compressed_output_l(struct stream_out *out)
1227{
1228 out->offload_state = OFFLOAD_STATE_IDLE;
1229 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001230 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001231 if (out->compr != NULL) {
1232 compress_stop(out->compr);
1233 while (out->offload_thread_blocked) {
1234 pthread_cond_wait(&out->cond, &out->lock);
1235 }
1236 }
1237}
1238
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001239bool is_offload_usecase(audio_usecase_t uc_id)
1240{
1241 unsigned int i;
1242 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1243 if (uc_id == offload_usecases[i])
1244 return true;
1245 }
1246 return false;
1247}
1248
vivek mehta446c3962015-09-14 10:57:35 -07001249static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001250{
vivek mehta446c3962015-09-14 10:57:35 -07001251 audio_usecase_t ret_uc = USECASE_INVALID;
1252 unsigned int offload_uc_index;
1253 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1254 if (!adev->multi_offload_enable) {
1255 if (is_direct_pcm)
1256 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1257 else
1258 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001259
vivek mehta446c3962015-09-14 10:57:35 -07001260 pthread_mutex_lock(&adev->lock);
1261 if (get_usecase_from_list(adev, ret_uc) != NULL)
1262 ret_uc = USECASE_INVALID;
1263 pthread_mutex_unlock(&adev->lock);
1264
1265 return ret_uc;
1266 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001267
1268 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001269 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1270 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1271 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1272 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001273 break;
1274 }
1275 }
vivek mehta446c3962015-09-14 10:57:35 -07001276
1277 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1278 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001279}
1280
1281static void free_offload_usecase(struct audio_device *adev,
1282 audio_usecase_t uc_id)
1283{
vivek mehta446c3962015-09-14 10:57:35 -07001284 unsigned int offload_uc_index;
1285 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1286
1287 if (!adev->multi_offload_enable)
1288 return;
1289
1290 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1291 if (offload_usecases[offload_uc_index] == uc_id) {
1292 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001293 break;
1294 }
1295 }
1296 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1297}
1298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001299static void *offload_thread_loop(void *context)
1300{
1301 struct stream_out *out = (struct stream_out *) context;
1302 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001303 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1306 set_sched_policy(0, SP_FOREGROUND);
1307 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1308
1309 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001310 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001311 for (;;) {
1312 struct offload_cmd *cmd = NULL;
1313 stream_callback_event_t event;
1314 bool send_callback = false;
1315
1316 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1317 __func__, list_empty(&out->offload_cmd_list),
1318 out->offload_state);
1319 if (list_empty(&out->offload_cmd_list)) {
1320 ALOGV("%s SLEEPING", __func__);
1321 pthread_cond_wait(&out->offload_cond, &out->lock);
1322 ALOGV("%s RUNNING", __func__);
1323 continue;
1324 }
1325
1326 item = list_head(&out->offload_cmd_list);
1327 cmd = node_to_item(item, struct offload_cmd, node);
1328 list_remove(item);
1329
1330 ALOGVV("%s STATE %d CMD %d out->compr %p",
1331 __func__, out->offload_state, cmd->cmd, out->compr);
1332
1333 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1334 free(cmd);
1335 break;
1336 }
1337
1338 if (out->compr == NULL) {
1339 ALOGE("%s: Compress handle is NULL", __func__);
1340 pthread_cond_signal(&out->cond);
1341 continue;
1342 }
1343 out->offload_thread_blocked = true;
1344 pthread_mutex_unlock(&out->lock);
1345 send_callback = false;
1346 switch(cmd->cmd) {
1347 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001348 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001349 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001350 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001351 send_callback = true;
1352 event = STREAM_CBK_EVENT_WRITE_READY;
1353 break;
1354 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001355 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301356 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001357 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301358 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001359 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301360 if (ret < 0)
1361 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301362 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301363 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001364 compress_drain(out->compr);
1365 else
1366 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301367 if (ret != -ENETRESET) {
1368 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301369 pthread_mutex_lock(&out->lock);
1370 out->send_new_metadata = 1;
1371 out->send_next_track_params = true;
1372 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301373 event = STREAM_CBK_EVENT_DRAIN_READY;
1374 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1375 } else
1376 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001377 break;
1378 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001379 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001380 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001381 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001382 send_callback = true;
1383 event = STREAM_CBK_EVENT_DRAIN_READY;
1384 break;
1385 default:
1386 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1387 break;
1388 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001389 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001390 out->offload_thread_blocked = false;
1391 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001392 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001393 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001394 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001395 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001396 free(cmd);
1397 }
1398
1399 pthread_cond_signal(&out->cond);
1400 while (!list_empty(&out->offload_cmd_list)) {
1401 item = list_head(&out->offload_cmd_list);
1402 list_remove(item);
1403 free(node_to_item(item, struct offload_cmd, node));
1404 }
1405 pthread_mutex_unlock(&out->lock);
1406
1407 return NULL;
1408}
1409
1410static int create_offload_callback_thread(struct stream_out *out)
1411{
1412 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1413 list_init(&out->offload_cmd_list);
1414 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1415 offload_thread_loop, out);
1416 return 0;
1417}
1418
1419static int destroy_offload_callback_thread(struct stream_out *out)
1420{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001421 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001422 stop_compressed_output_l(out);
1423 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1424
1425 pthread_mutex_unlock(&out->lock);
1426 pthread_join(out->offload_thread, (void **) NULL);
1427 pthread_cond_destroy(&out->offload_cond);
1428
1429 return 0;
1430}
1431
Eric Laurent07eeafd2013-10-06 12:52:49 -07001432static bool allow_hdmi_channel_config(struct audio_device *adev)
1433{
1434 struct listnode *node;
1435 struct audio_usecase *usecase;
1436 bool ret = true;
1437
1438 list_for_each(node, &adev->usecase_list) {
1439 usecase = node_to_item(node, struct audio_usecase, list);
1440 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1441 /*
1442 * If voice call is already existing, do not proceed further to avoid
1443 * disabling/enabling both RX and TX devices, CSD calls, etc.
1444 * Once the voice call done, the HDMI channels can be configured to
1445 * max channels of remaining use cases.
1446 */
1447 if (usecase->id == USECASE_VOICE_CALL) {
1448 ALOGD("%s: voice call is active, no change in HDMI channels",
1449 __func__);
1450 ret = false;
1451 break;
1452 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1453 ALOGD("%s: multi channel playback is active, "
1454 "no change in HDMI channels", __func__);
1455 ret = false;
1456 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001457 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001458 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001459 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1460 ", no change in HDMI channels", __func__,
1461 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001462 ret = false;
1463 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001464 }
1465 }
1466 }
1467 return ret;
1468}
1469
1470static int check_and_set_hdmi_channels(struct audio_device *adev,
1471 unsigned int channels)
1472{
1473 struct listnode *node;
1474 struct audio_usecase *usecase;
1475
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001476 unsigned int supported_channels = platform_edid_get_max_channels(
1477 adev->platform);
1478 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001479 /* Check if change in HDMI channel config is allowed */
1480 if (!allow_hdmi_channel_config(adev))
1481 return 0;
1482
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001483 if (channels > supported_channels)
1484 channels = supported_channels;
1485
Eric Laurent07eeafd2013-10-06 12:52:49 -07001486 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001487 ALOGD("%s: Requested channels are same as current channels(%d)",
1488 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001489 return 0;
1490 }
1491
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001492 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001493 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001494 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001495 adev->cur_hdmi_channels = channels;
1496
1497 /*
1498 * Deroute all the playback streams routed to HDMI so that
1499 * the back end is deactivated. Note that backend will not
1500 * be deactivated if any one stream is connected to it.
1501 */
1502 list_for_each(node, &adev->usecase_list) {
1503 usecase = node_to_item(node, struct audio_usecase, list);
1504 if (usecase->type == PCM_PLAYBACK &&
1505 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001506 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001507 }
1508 }
1509
1510 /*
1511 * Enable all the streams disabled above. Now the HDMI backend
1512 * will be activated with new channel configuration
1513 */
1514 list_for_each(node, &adev->usecase_list) {
1515 usecase = node_to_item(node, struct audio_usecase, list);
1516 if (usecase->type == PCM_PLAYBACK &&
1517 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001518 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001519 }
1520 }
1521
1522 return 0;
1523}
1524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525static int stop_output_stream(struct stream_out *out)
1526{
1527 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 struct audio_usecase *uc_info;
1529 struct audio_device *adev = out->dev;
1530
Eric Laurent994a6932013-07-17 11:51:42 -07001531 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 uc_info = get_usecase_from_list(adev, out->usecase);
1534 if (uc_info == NULL) {
1535 ALOGE("%s: Could not find the usecase (%d) in the list",
1536 __func__, out->usecase);
1537 return -EINVAL;
1538 }
1539
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001540 if (is_offload_usecase(out->usecase) &&
1541 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001542 if (adev->visualizer_stop_output != NULL)
1543 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001544
1545 audio_extn_dts_remove_state_notifier_node(out->usecase);
1546
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001547 if (adev->offload_effects_stop_output != NULL)
1548 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1549 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001550
Eric Laurent150dbfe2013-02-27 14:31:02 -08001551 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001552 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553
1554 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001555 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001557 list_remove(&uc_info->list);
1558 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001560 if (is_offload_usecase(out->usecase) &&
1561 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1562 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1563 ALOGV("Disable passthrough , reset mixer to pcm");
1564 /* NO_PASSTHROUGH */
1565 out->compr_config.codec->compr_passthr = 0;
1566 audio_extn_dolby_set_hdmi_config(adev, out);
1567 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1568 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001569 /* Must be called after removing the usecase from list */
1570 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1571 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1572
Eric Laurent994a6932013-07-17 11:51:42 -07001573 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574 return ret;
1575}
1576
1577int start_output_stream(struct stream_out *out)
1578{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001580 int sink_channels = 0;
1581 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 struct audio_usecase *uc_info;
1583 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301584 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001586 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1587 ret = -EINVAL;
1588 goto error_config;
1589 }
1590
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301591 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1592 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1593 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301594
Naresh Tanniru80659832014-06-04 18:17:56 +05301595 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301596 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301597 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301598 goto error_config;
1599 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301600
Eric Laurentb23d5282013-05-14 15:27:20 -07001601 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602 if (out->pcm_device_id < 0) {
1603 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1604 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001605 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001606 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 }
1608
1609 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001610
1611 if (!uc_info) {
1612 ret = -ENOMEM;
1613 goto error_config;
1614 }
1615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 uc_info->id = out->usecase;
1617 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001618 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 uc_info->devices = out->devices;
1620 uc_info->in_snd_device = SND_DEVICE_NONE;
1621 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001622 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001623 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001624 if (is_offload_usecase(out->usecase)) {
1625 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001626 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1627 }
1628 }
Mingming Yin9c041392014-05-01 15:37:31 -07001629 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1630 if (!strncmp("true", prop_value, 4)) {
1631 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001632 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1633 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001634 check_and_set_hdmi_channels(adev, sink_channels);
1635 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001636 if (is_offload_usecase(out->usecase)) {
1637 unsigned int ch_count = out->compr_config.codec->ch_in;
1638 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1639 /* backend channel config for passthrough stream is stereo */
1640 ch_count = 2;
1641 check_and_set_hdmi_channels(adev, ch_count);
1642 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001643 check_and_set_hdmi_channels(adev, out->config.channels);
1644 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001645 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001646 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001647 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301649 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1650 adev->perf_lock_opts,
1651 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 select_devices(adev, out->usecase);
1653
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001654 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1655 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001656 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001657 unsigned int flags = PCM_OUT;
1658 unsigned int pcm_open_retry_count = 0;
1659 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1660 flags |= PCM_MMAP | PCM_NOIRQ;
1661 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1662 } else
1663 flags |= PCM_MONOTONIC;
1664
1665 while (1) {
1666 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1667 flags, &out->config);
1668 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1669 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1670 if (out->pcm != NULL) {
1671 pcm_close(out->pcm);
1672 out->pcm = NULL;
1673 }
1674 if (pcm_open_retry_count-- == 0) {
1675 ret = -EIO;
1676 goto error_open;
1677 }
1678 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1679 continue;
1680 }
1681 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001682 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001683
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001684 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1685 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001686
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001687 ALOGV("%s: pcm_prepare", __func__);
1688 if (pcm_is_ready(out->pcm)) {
1689 ret = pcm_prepare(out->pcm);
1690 if (ret < 0) {
1691 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1692 pcm_close(out->pcm);
1693 out->pcm = NULL;
1694 goto error_open;
1695 }
1696 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001697 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001698 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1699 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001701 out->compr = compress_open(adev->snd_card,
1702 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001703 COMPRESS_IN, &out->compr_config);
1704 if (out->compr && !is_compress_ready(out->compr)) {
1705 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1706 compress_close(out->compr);
1707 out->compr = NULL;
1708 ret = -EIO;
1709 goto error_open;
1710 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301711 /* compress_open sends params of the track, so reset the flag here */
1712 out->is_compr_metadata_avail = false;
1713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 if (out->offload_callback)
1715 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001716
Fred Oh3f43e742015-03-04 18:42:34 -08001717 /* Since small bufs uses blocking writes, a write will be blocked
1718 for the default max poll time (20s) in the event of an SSR.
1719 Reduce the poll time to observe and deal with SSR faster.
1720 */
1721 if (out->use_small_bufs) {
1722 compress_set_max_poll_wait(out->compr, 1000);
1723 }
1724
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001725 audio_extn_dts_create_state_notifier_node(out->usecase);
1726 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1727 popcount(out->channel_mask),
1728 out->playback_started);
1729
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001730#ifdef DS1_DOLBY_DDP_ENABLED
1731 if (audio_extn_is_dolby_format(out->format))
1732 audio_extn_dolby_send_ddp_endp_params(adev);
1733#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001734 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1735 if (adev->visualizer_start_output != NULL)
1736 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1737 if (adev->offload_effects_start_output != NULL)
1738 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001739 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001740 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301742 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001743 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301747 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001749error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301750 /*
1751 * sleep 50ms to allow sufficient time for kernel
1752 * drivers to recover incases like SSR.
1753 */
1754 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001755 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756}
1757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758static int check_input_parameters(uint32_t sample_rate,
1759 audio_format_t format,
1760 int channel_count)
1761{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001762 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001764 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001765 !voice_extn_compress_voip_is_format_supported(format) &&
1766 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001767
1768 switch (channel_count) {
1769 case 1:
1770 case 2:
1771 case 6:
1772 break;
1773 default:
1774 ret = -EINVAL;
1775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
1777 switch (sample_rate) {
1778 case 8000:
1779 case 11025:
1780 case 12000:
1781 case 16000:
1782 case 22050:
1783 case 24000:
1784 case 32000:
1785 case 44100:
1786 case 48000:
1787 break;
1788 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001789 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 }
1791
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001792 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793}
1794
1795static size_t get_input_buffer_size(uint32_t sample_rate,
1796 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001797 int channel_count,
1798 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 size_t size = 0;
1801
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001802 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1803 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001805 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001806 if (is_low_latency)
1807 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001808 /* ToDo: should use frame_size computed based on the format and
1809 channel_count here. */
1810 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001812 /* make sure the size is multiple of 32 bytes
1813 * At 48 kHz mono 16-bit PCM:
1814 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1815 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1816 */
1817 size += 0x1f;
1818 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001819
1820 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821}
1822
1823static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1824{
1825 struct stream_out *out = (struct stream_out *)stream;
1826
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001827 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828}
1829
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001830static int out_set_sample_rate(struct audio_stream *stream __unused,
1831 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832{
1833 return -ENOSYS;
1834}
1835
1836static size_t out_get_buffer_size(const struct audio_stream *stream)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001840 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001841 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001842 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1843 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001844
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001845 return out->config.period_size *
1846 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847}
1848
1849static uint32_t out_get_channels(const struct audio_stream *stream)
1850{
1851 struct stream_out *out = (struct stream_out *)stream;
1852
1853 return out->channel_mask;
1854}
1855
1856static audio_format_t out_get_format(const struct audio_stream *stream)
1857{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 struct stream_out *out = (struct stream_out *)stream;
1859
1860 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861}
1862
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001863static int out_set_format(struct audio_stream *stream __unused,
1864 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865{
1866 return -ENOSYS;
1867}
1868
1869static int out_standby(struct audio_stream *stream)
1870{
1871 struct stream_out *out = (struct stream_out *)stream;
1872 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001873
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301874 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1875 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001876 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1877 /* Ignore standby in case of voip call because the voip output
1878 * stream is closed in adev_close_output_stream()
1879 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301880 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001881 return 0;
1882 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001884 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001886 if (adev->adm_deregister_stream)
1887 adev->adm_deregister_stream(adev->adm_data, out->handle);
1888
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001889 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001891 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001892 if (out->pcm) {
1893 pcm_close(out->pcm);
1894 out->pcm = NULL;
1895 }
1896 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001897 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301899 out->send_next_track_params = false;
1900 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001901 out->gapless_mdata.encoder_delay = 0;
1902 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001903 if (out->compr != NULL) {
1904 compress_close(out->compr);
1905 out->compr = NULL;
1906 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001907 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001909 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 }
1911 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001912 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 return 0;
1914}
1915
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001916static int out_dump(const struct audio_stream *stream __unused,
1917 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918{
1919 return 0;
1920}
1921
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001922static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1923{
1924 int ret = 0;
1925 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001926
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001927 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001928 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001929 return -EINVAL;
1930 }
1931
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301932 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001933
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1935 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301936 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001937 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1939 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301940 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001941 }
1942
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001943 ALOGV("%s new encoder delay %u and padding %u", __func__,
1944 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1945
1946 return 0;
1947}
1948
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001949static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1950{
1951 return out == adev->primary_output || out == adev->voice_tx_output;
1952}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1955{
1956 struct stream_out *out = (struct stream_out *)stream;
1957 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001958 struct audio_usecase *usecase;
1959 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 struct str_parms *parms;
1961 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001962 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001963 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964
sangwoobc677242013-08-08 16:53:43 +09001965 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001966 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301968 if (!parms)
1969 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001970 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1971 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001973 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001974 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301977 * When HDMI cable is unplugged/usb hs is disconnected the
1978 * music playback is paused and the policy manager sends routing=0
1979 * But the audioflingercontinues to write data until standby time
1980 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 * Avoid this by routing audio to speaker until standby.
1982 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301983 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1984 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001985 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001986 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1987 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001988 }
1989
1990 /*
1991 * select_devices() call below switches all the usecases on the same
1992 * backend to the new device. Refer to check_usecases_codec_backend() in
1993 * the select_devices(). But how do we undo this?
1994 *
1995 * For example, music playback is active on headset (deep-buffer usecase)
1996 * and if we go to ringtones and select a ringtone, low-latency usecase
1997 * will be started on headset+speaker. As we can't enable headset+speaker
1998 * and headset devices at the same time, select_devices() switches the music
1999 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2000 * So when the ringtone playback is completed, how do we undo the same?
2001 *
2002 * We are relying on the out_set_parameters() call on deep-buffer output,
2003 * once the ringtone playback is ended.
2004 * NOTE: We should not check if the current devices are same as new devices.
2005 * Because select_devices() must be called to switch back the music
2006 * playback to headset.
2007 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002008 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002009 out->devices = val;
2010
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302011 if (!out->standby) {
2012 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2013 adev->perf_lock_opts,
2014 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002015 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302016 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2017 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002018
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002019 if (output_drives_call(adev, out)) {
2020 if(!voice_is_in_call(adev)) {
2021 if (adev->mode == AUDIO_MODE_IN_CALL) {
2022 adev->current_call_output = out;
2023 ret = voice_start_call(adev);
2024 }
2025 } else {
2026 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002027 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002028 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002029 }
2030 }
2031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002033 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002035
2036 if (out == adev->primary_output) {
2037 pthread_mutex_lock(&adev->lock);
2038 audio_extn_set_parameters(adev, parms);
2039 pthread_mutex_unlock(&adev->lock);
2040 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002041 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002042 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002043 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002044
2045 audio_extn_dts_create_state_notifier_node(out->usecase);
2046 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2047 popcount(out->channel_mask),
2048 out->playback_started);
2049
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002050 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002051 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002052
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302054error:
Eric Laurent994a6932013-07-17 11:51:42 -07002055 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056 return ret;
2057}
2058
2059static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2060{
2061 struct stream_out *out = (struct stream_out *)stream;
2062 struct str_parms *query = str_parms_create_str(keys);
2063 char *str;
2064 char value[256];
2065 struct str_parms *reply = str_parms_create();
2066 size_t i, j;
2067 int ret;
2068 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002069
2070 if (!query || !reply) {
2071 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2072 return NULL;
2073 }
2074
Eric Laurent994a6932013-07-17 11:51:42 -07002075 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2077 if (ret >= 0) {
2078 value[0] = '\0';
2079 i = 0;
2080 while (out->supported_channel_masks[i] != 0) {
2081 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2082 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2083 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002084 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002086 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 first = false;
2088 break;
2089 }
2090 }
2091 i++;
2092 }
2093 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2094 str = str_parms_to_str(reply);
2095 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002096 voice_extn_out_get_parameters(out, query, reply);
2097 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002098 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002099 free(str);
2100 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002101 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002103
Alexy Joseph62142aa2015-11-16 15:10:34 -08002104
2105 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2106 if (ret >= 0) {
2107 value[0] = '\0';
2108 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2109 ALOGV("in direct_pcm");
2110 strlcat(value, "true", strlen("true"));
2111 } else {
2112 ALOGV("not in direct_pcm");
2113 strlcat(value, "false", strlen("false"));
2114 }
2115 str_parms_add_str(reply, "is_direct_pcm_track", value);
2116 str = str_parms_to_str(reply);
2117 }
2118
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002119 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2120 if (ret >= 0) {
2121 value[0] = '\0';
2122 i = 0;
2123 first = true;
2124 while (out->supported_formats[i] != 0) {
2125 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2126 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2127 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002128 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002129 }
2130 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2131 first = false;
2132 break;
2133 }
2134 }
2135 i++;
2136 }
2137 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2138 str = str_parms_to_str(reply);
2139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 str_parms_destroy(query);
2141 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002142 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 return str;
2144}
2145
2146static uint32_t out_get_latency(const struct audio_stream_out *stream)
2147{
2148 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002149 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150
Alexy Josephaa54c872014-12-03 02:46:47 -08002151 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002152 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002153 } else {
2154 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002156 }
2157
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302158 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002159 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160}
2161
2162static int out_set_volume(struct audio_stream_out *stream, float left,
2163 float right)
2164{
Eric Laurenta9024de2013-04-04 09:19:12 -07002165 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002166 int volume[2];
2167
Eric Laurenta9024de2013-04-04 09:19:12 -07002168 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2169 /* only take left channel into account: the API is for stereo anyway */
2170 out->muted = (left == 0.0f);
2171 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002172 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002173 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2174 /*
2175 * Set mute or umute on HDMI passthrough stream.
2176 * Only take left channel into account.
2177 * Mute is 0 and unmute 1
2178 */
2179 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2180 } else {
2181 char mixer_ctl_name[128];
2182 struct audio_device *adev = out->dev;
2183 struct mixer_ctl *ctl;
2184 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002185 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002186
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002187 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2188 "Compress Playback %d Volume", pcm_device_id);
2189 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2190 if (!ctl) {
2191 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2192 __func__, mixer_ctl_name);
2193 return -EINVAL;
2194 }
2195 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2196 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2197 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2198 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002200 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 return -ENOSYS;
2203}
2204
2205static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2206 size_t bytes)
2207{
2208 struct stream_out *out = (struct stream_out *)stream;
2209 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302210 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002211 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002213 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302214
Naresh Tanniru80659832014-06-04 18:17:56 +05302215 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002216 // increase written size during SSR to avoid mismatch
2217 // with the written frames count in AF
2218 if (!is_offload_usecase(out->usecase))
2219 out->written += bytes / (out->config.channels * sizeof(short));
2220
Naresh Tanniru80659832014-06-04 18:17:56 +05302221 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302222 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302223 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302224 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002225 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302226 //during SSR for compress usecase we should return error to flinger
2227 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2228 pthread_mutex_unlock(&out->lock);
2229 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302230 }
2231 }
2232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002234 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002235 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002236 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2237 ret = voice_extn_compress_voip_start_output_stream(out);
2238 else
2239 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002240 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002241 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002243 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 goto exit;
2245 }
vivek mehta446c3962015-09-14 10:57:35 -07002246 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002247 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Ashish Jain81eb2a82015-05-13 10:52:34 +05302250 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2251 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2252 adev->is_channel_status_set = true;
2253 }
2254
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002255 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002256 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002257 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002258 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002259 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2260 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302261 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2262 ALOGD("copl(%p):send next track params in gapless", out);
2263 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2264 out->send_next_track_params = false;
2265 out->is_compr_metadata_avail = false;
2266 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002267 }
2268
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302270 if (ret < 0)
2271 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002272 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002273 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302274 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002275 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302276 } else if (-ENETRESET == ret) {
2277 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2278 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2279 pthread_mutex_unlock(&out->lock);
2280 out_standby(&out->stream.common);
2281 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002282 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302283 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002285 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 out->playback_started = 1;
2287 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002288
2289 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2290 popcount(out->channel_mask),
2291 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 }
2293 pthread_mutex_unlock(&out->lock);
2294 return ret;
2295 } else {
2296 if (out->pcm) {
2297 if (out->muted)
2298 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002299
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002301
2302 if (adev->adm_request_focus)
2303 adev->adm_request_focus(adev->adm_data, out->handle);
2304
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002305 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2306 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2307 else
2308 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002309
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302310 if (ret < 0)
2311 ret = -errno;
2312 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002313 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002314
2315 if (adev->adm_abandon_focus)
2316 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318 }
2319
2320exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302321 /* ToDo: There may be a corner case when SSR happens back to back during
2322 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302323 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302324 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302325 }
2326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327 pthread_mutex_unlock(&out->lock);
2328
2329 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002330 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002331 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302332 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302333 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302334 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302335 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302336 out->standby = true;
2337 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002339 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302340 out_get_sample_rate(&out->stream.common));
2341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342 }
2343 return bytes;
2344}
2345
2346static int out_get_render_position(const struct audio_stream_out *stream,
2347 uint32_t *dsp_frames)
2348{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002349 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302350 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002351
2352 if (dsp_frames == NULL)
2353 return -EINVAL;
2354
2355 *dsp_frames = 0;
2356 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002357 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002358 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302360 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302362 if (ret < 0)
2363 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 ALOGVV("%s rendered frames %d sample_rate %d",
2365 __func__, *dsp_frames, out->sample_rate);
2366 }
2367 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302368 if (-ENETRESET == ret) {
2369 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2370 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2371 return -EINVAL;
2372 } else if(ret < 0) {
2373 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2374 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302375 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2376 /*
2377 * Handle corner case where compress session is closed during SSR
2378 * and timestamp is queried
2379 */
2380 ALOGE(" ERROR: sound card not active, return error");
2381 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302382 } else {
2383 return 0;
2384 }
Zhou Song32a556e2015-05-05 10:46:56 +08002385 } else if (audio_is_linear_pcm(out->format)) {
2386 *dsp_frames = out->written;
2387 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 } else
2389 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390}
2391
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002392static int out_add_audio_effect(const struct audio_stream *stream __unused,
2393 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394{
2395 return 0;
2396}
2397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002398static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2399 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400{
2401 return 0;
2402}
2403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002404static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2405 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406{
2407 return -EINVAL;
2408}
2409
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002410static int out_get_presentation_position(const struct audio_stream_out *stream,
2411 uint64_t *frames, struct timespec *timestamp)
2412{
2413 struct stream_out *out = (struct stream_out *)stream;
2414 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002415 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002416
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002417 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002418
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002419 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002420 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302421 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002422 &out->sample_rate);
2423 ALOGVV("%s rendered frames %ld sample_rate %d",
2424 __func__, dsp_frames, out->sample_rate);
2425 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302426 if (ret < 0)
2427 ret = -errno;
2428 if (-ENETRESET == ret) {
2429 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2430 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2431 ret = -EINVAL;
2432 } else
2433 ret = 0;
2434
Eric Laurent949a0892013-09-20 09:20:13 -07002435 /* this is the best we can do */
2436 clock_gettime(CLOCK_MONOTONIC, timestamp);
2437 }
2438 } else {
2439 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002440 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002441 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2442 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002443 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002444 // This adjustment accounts for buffering after app processor.
2445 // It is based on estimated DSP latency per use case, rather than exact.
2446 signed_frames -=
2447 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2448
Eric Laurent949a0892013-09-20 09:20:13 -07002449 // It would be unusual for this value to be negative, but check just in case ...
2450 if (signed_frames >= 0) {
2451 *frames = signed_frames;
2452 ret = 0;
2453 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002454 }
2455 }
2456 }
2457
2458 pthread_mutex_unlock(&out->lock);
2459
2460 return ret;
2461}
2462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463static int out_set_callback(struct audio_stream_out *stream,
2464 stream_callback_t callback, void *cookie)
2465{
2466 struct stream_out *out = (struct stream_out *)stream;
2467
2468 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002469 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 out->offload_callback = callback;
2471 out->offload_cookie = cookie;
2472 pthread_mutex_unlock(&out->lock);
2473 return 0;
2474}
2475
2476static int out_pause(struct audio_stream_out* stream)
2477{
2478 struct stream_out *out = (struct stream_out *)stream;
2479 int status = -ENOSYS;
2480 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002481 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002482 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002483 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302485 struct audio_device *adev = out->dev;
2486 int snd_scard_state = get_snd_card_state(adev);
2487
2488 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2489 status = compress_pause(out->compr);
2490
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002492
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302493 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002494 audio_extn_dts_notify_playback_state(out->usecase, 0,
2495 out->sample_rate, popcount(out->channel_mask),
2496 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 }
2498 pthread_mutex_unlock(&out->lock);
2499 }
2500 return status;
2501}
2502
2503static int out_resume(struct audio_stream_out* stream)
2504{
2505 struct stream_out *out = (struct stream_out *)stream;
2506 int status = -ENOSYS;
2507 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002508 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002509 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002510 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002512 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302513 struct audio_device *adev = out->dev;
2514 int snd_scard_state = get_snd_card_state(adev);
2515
2516 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2517 status = compress_resume(out->compr);
2518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002520
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302521 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002522 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2523 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524 }
2525 pthread_mutex_unlock(&out->lock);
2526 }
2527 return status;
2528}
2529
2530static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2531{
2532 struct stream_out *out = (struct stream_out *)stream;
2533 int status = -ENOSYS;
2534 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002535 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002536 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002537 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2538 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2539 else
2540 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2541 pthread_mutex_unlock(&out->lock);
2542 }
2543 return status;
2544}
2545
2546static int out_flush(struct audio_stream_out* stream)
2547{
2548 struct stream_out *out = (struct stream_out *)stream;
2549 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002550 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002551 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002552 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002553 stop_compressed_output_l(out);
2554 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002555 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 return 0;
2557 }
2558 return -ENOSYS;
2559}
2560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561/** audio_stream_in implementation **/
2562static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2563{
2564 struct stream_in *in = (struct stream_in *)stream;
2565
2566 return in->config.rate;
2567}
2568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002569static int in_set_sample_rate(struct audio_stream *stream __unused,
2570 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571{
2572 return -ENOSYS;
2573}
2574
2575static size_t in_get_buffer_size(const struct audio_stream *stream)
2576{
2577 struct stream_in *in = (struct stream_in *)stream;
2578
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002579 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2580 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002581 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2582 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002583
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002584 return in->config.period_size *
2585 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586}
2587
2588static uint32_t in_get_channels(const struct audio_stream *stream)
2589{
2590 struct stream_in *in = (struct stream_in *)stream;
2591
2592 return in->channel_mask;
2593}
2594
2595static audio_format_t in_get_format(const struct audio_stream *stream)
2596{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002597 struct stream_in *in = (struct stream_in *)stream;
2598
2599 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600}
2601
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002602static int in_set_format(struct audio_stream *stream __unused,
2603 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604{
2605 return -ENOSYS;
2606}
2607
2608static int in_standby(struct audio_stream *stream)
2609{
2610 struct stream_in *in = (struct stream_in *)stream;
2611 struct audio_device *adev = in->dev;
2612 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302613 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2614 stream, in->usecase, use_case_table[in->usecase]);
2615
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002616 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2617 /* Ignore standby in case of voip call because the voip input
2618 * stream is closed in adev_close_input_stream()
2619 */
2620 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2621 return status;
2622 }
2623
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002624 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002625 if (!in->standby && in->is_st_session) {
2626 ALOGD("%s: sound trigger pcm stop lab", __func__);
2627 audio_extn_sound_trigger_stop_lab(in);
2628 in->standby = 1;
2629 }
2630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002632 if (adev->adm_deregister_stream)
2633 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2634
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002635 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002637 if (in->pcm) {
2638 pcm_close(in->pcm);
2639 in->pcm = NULL;
2640 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002642 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 }
2644 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002645 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 return status;
2647}
2648
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002649static int in_dump(const struct audio_stream *stream __unused,
2650 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651{
2652 return 0;
2653}
2654
2655static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2656{
2657 struct stream_in *in = (struct stream_in *)stream;
2658 struct audio_device *adev = in->dev;
2659 struct str_parms *parms;
2660 char *str;
2661 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002662 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302664 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 parms = str_parms_create_str(kvpairs);
2666
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302667 if (!parms)
2668 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002669 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002670 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002671
2672 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2673 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 val = atoi(value);
2675 /* no audio source uses val == 0 */
2676 if ((in->source != val) && (val != 0)) {
2677 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002678 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2679 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2680 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2681 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002682 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002683 err = voice_extn_compress_voip_open_input_stream(in);
2684 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002685 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002686 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002687 }
2688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 }
2690 }
2691
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002692 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2693 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002695 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 in->device = val;
2697 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002698 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002699 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 }
2701 }
2702
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002703done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002705 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706
2707 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302708error:
Eric Laurent994a6932013-07-17 11:51:42 -07002709 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 return ret;
2711}
2712
2713static char* in_get_parameters(const struct audio_stream *stream,
2714 const char *keys)
2715{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002716 struct stream_in *in = (struct stream_in *)stream;
2717 struct str_parms *query = str_parms_create_str(keys);
2718 char *str;
2719 char value[256];
2720 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002721
2722 if (!query || !reply) {
2723 ALOGE("in_get_parameters: failed to create query or reply");
2724 return NULL;
2725 }
2726
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002727 ALOGV("%s: enter: keys - %s", __func__, keys);
2728
2729 voice_extn_in_get_parameters(in, query, reply);
2730
2731 str = str_parms_to_str(reply);
2732 str_parms_destroy(query);
2733 str_parms_destroy(reply);
2734
2735 ALOGV("%s: exit: returns - %s", __func__, str);
2736 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737}
2738
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002739static int in_set_gain(struct audio_stream_in *stream __unused,
2740 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741{
2742 return 0;
2743}
2744
2745static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2746 size_t bytes)
2747{
2748 struct stream_in *in = (struct stream_in *)stream;
2749 struct audio_device *adev = in->dev;
2750 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302751 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002753 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302754
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002755 if (in->is_st_session) {
2756 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2757 /* Read from sound trigger HAL */
2758 audio_extn_sound_trigger_read(in, buffer, bytes);
2759 pthread_mutex_unlock(&in->lock);
2760 return bytes;
2761 }
2762
2763 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2764 ALOGD(" %s: sound card is not active/SSR state", __func__);
2765 ret= -EIO;;
2766 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302767 }
2768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002770 pthread_mutex_lock(&adev->lock);
2771 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2772 ret = voice_extn_compress_voip_start_input_stream(in);
2773 else
2774 ret = start_input_stream(in);
2775 pthread_mutex_unlock(&adev->lock);
2776 if (ret != 0) {
2777 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 }
2779 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002780 if (adev->adm_register_input_stream)
2781 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002784 if (adev->adm_request_focus)
2785 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2786
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002788 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002789 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002790 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2791 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002792 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2793 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002794 else
2795 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302796 if (ret < 0)
2797 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 }
2799
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002800 if (adev->adm_abandon_focus)
2801 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 /*
2804 * Instead of writing zeroes here, we could trust the hardware
2805 * to always provide zeroes when muted.
2806 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302807 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2808 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 memset(buffer, 0, bytes);
2810
2811exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302812 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302813 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002814 if (-ENETRESET == ret)
2815 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 pthread_mutex_unlock(&in->lock);
2818
2819 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302820 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302821 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302822 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302823 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302824 in->standby = true;
2825 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302826 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002828 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002829 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302830 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 }
2832 return bytes;
2833}
2834
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002835static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836{
2837 return 0;
2838}
2839
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002840static int add_remove_audio_effect(const struct audio_stream *stream,
2841 effect_handle_t effect,
2842 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002844 struct stream_in *in = (struct stream_in *)stream;
2845 int status = 0;
2846 effect_descriptor_t desc;
2847
2848 status = (*effect)->get_descriptor(effect, &desc);
2849 if (status != 0)
2850 return status;
2851
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002852 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002853 pthread_mutex_lock(&in->dev->lock);
2854 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2855 in->enable_aec != enable &&
2856 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2857 in->enable_aec = enable;
2858 if (!in->standby)
2859 select_devices(in->dev, in->usecase);
2860 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002861 if (in->enable_ns != enable &&
2862 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2863 in->enable_ns = enable;
2864 if (!in->standby)
2865 select_devices(in->dev, in->usecase);
2866 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002867 pthread_mutex_unlock(&in->dev->lock);
2868 pthread_mutex_unlock(&in->lock);
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 return 0;
2871}
2872
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002873static int in_add_audio_effect(const struct audio_stream *stream,
2874 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875{
Eric Laurent994a6932013-07-17 11:51:42 -07002876 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002877 return add_remove_audio_effect(stream, effect, true);
2878}
2879
2880static int in_remove_audio_effect(const struct audio_stream *stream,
2881 effect_handle_t effect)
2882{
Eric Laurent994a6932013-07-17 11:51:42 -07002883 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002884 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885}
2886
2887static int adev_open_output_stream(struct audio_hw_device *dev,
2888 audio_io_handle_t handle,
2889 audio_devices_t devices,
2890 audio_output_flags_t flags,
2891 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002892 struct audio_stream_out **stream_out,
2893 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894{
2895 struct audio_device *adev = (struct audio_device *)dev;
2896 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002897 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002898 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302901
2902 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2903 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002904 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302905 return -EINVAL;
2906 }
2907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2909
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302910 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2911 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2912 devices, flags, &out->stream);
2913
2914
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002915 if (!out) {
2916 return -ENOMEM;
2917 }
2918
Haynes Mathew George204045b2015-02-25 20:32:03 -08002919 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002920 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002921 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 if (devices == AUDIO_DEVICE_NONE)
2924 devices = AUDIO_DEVICE_OUT_SPEAKER;
2925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 out->flags = flags;
2927 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002928 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002929 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 out->sample_rate = config->sample_rate;
2931 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2932 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002933 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002934 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002935 out->non_blocking = 0;
2936 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937
2938 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07002939 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2940 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002941 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2942 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2943
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002944 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002945 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2946 ret = read_hdmi_channel_masks(out);
2947
2948 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2949 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002950 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002951 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002952 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002953
2954 if (config->sample_rate == 0)
2955 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2956 if (config->channel_mask == 0)
2957 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2958
2959 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002960 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2962 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002964 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002966 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2967 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002968 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002969 ret = voice_extn_compress_voip_open_output_stream(out);
2970 if (ret != 0) {
2971 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2972 __func__, ret);
2973 goto error_open;
2974 }
vivek mehta0ea887a2015-08-26 14:01:20 -07002975 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2976 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2979 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2980 ALOGE("%s: Unsupported Offload information", __func__);
2981 ret = -EINVAL;
2982 goto error_open;
2983 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002984
2985 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2986 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2987 ALOGV("read and update_pass through formats");
2988 ret = audio_extn_dolby_update_passt_formats(adev, out);
2989 if(ret != 0) {
2990 goto error_open;
2991 }
2992 if(config->offload_info.format == 0)
2993 config->offload_info.format = out->supported_formats[0];
2994 }
2995
Mingming Yin90310102013-11-13 16:57:00 -08002996 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002997 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002998 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002999 ret = -EINVAL;
3000 goto error_open;
3001 }
3002
3003 out->compr_config.codec = (struct snd_codec *)
3004 calloc(1, sizeof(struct snd_codec));
3005
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003006 if (!out->compr_config.codec) {
3007 ret = -ENOMEM;
3008 goto error_open;
3009 }
3010
vivek mehta0ea887a2015-08-26 14:01:20 -07003011 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003012 out->usecase = get_offload_usecase(adev, true);
3013 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003014 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003015 out->stream.set_callback = out_set_callback;
3016 out->stream.pause = out_pause;
3017 out->stream.resume = out_resume;
3018 out->stream.drain = out_drain;
3019 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003020 out->usecase = get_offload_usecase(adev, false);
3021 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003022 }
vivek mehta446c3962015-09-14 10:57:35 -07003023
3024 if (out->usecase == USECASE_INVALID) {
3025 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3026 ret = -EEXIST;
3027 goto error_open;
3028 }
3029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 if (config->offload_info.channel_mask)
3031 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003032 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003034 config->offload_info.channel_mask = config->channel_mask;
3035 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003036 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003037 out->sample_rate = config->offload_info.sample_rate;
3038
Mingming Yin3ee55c62014-08-04 14:23:35 -07003039 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003041 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003042 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003043 audio_extn_dolby_get_snd_codec_id(adev, out,
3044 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003045 else
3046 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003048
3049 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3050 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003051 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003052 platform_get_pcm_offload_buffer_size(&config->offload_info);
3053 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3054 out->compr_config.fragment_size =
3055 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003056 } else {
3057 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003058 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003059 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3061 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003062 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 out->compr_config.codec->bit_rate =
3064 config->offload_info.bit_rate;
3065 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003066 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303068 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003069 /*TODO: Do we need to change it for passthrough */
3070 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071
Manish Dewangana6fc5442015-08-24 20:30:31 +05303072 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3073 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3074 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3075 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003076 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3077 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003078 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003079 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003080 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3081 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003082
Mingming Yin3ee55c62014-08-04 14:23:35 -07003083 if (out->bit_width == 24) {
3084 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3085 }
3086
Amit Shekhar6f461b12014-08-01 14:52:58 -07003087 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303088 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003089
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3091 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003092
Mingming Yin497419f2015-07-01 16:57:32 -07003093 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003094 //this flag is set from framework only if its for PCM formats
3095 //no need to check for PCM format again
3096 out->non_blocking = 0;
3097 out->use_small_bufs = true;
3098 ALOGI("Keep write blocking for small buff: non_blockling %d",
3099 out->non_blocking);
3100 }
3101
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003102 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303103 out->send_next_track_params = false;
3104 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003105 out->offload_state = OFFLOAD_STATE_IDLE;
3106 out->playback_started = 0;
3107
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003108 audio_extn_dts_create_state_notifier_node(out->usecase);
3109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 create_offload_callback_thread(out);
3111 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3112 __func__, config->offload_info.version,
3113 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003114 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003115 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003116 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3117 ret = voice_check_and_set_incall_music_usecase(adev, out);
3118 if (ret != 0) {
3119 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3120 __func__, ret);
3121 goto error_open;
3122 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003123 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3124 if (config->sample_rate == 0)
3125 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3126 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3127 config->sample_rate != 8000) {
3128 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3129 ret = -EINVAL;
3130 goto error_open;
3131 }
3132 out->sample_rate = config->sample_rate;
3133 out->config.rate = config->sample_rate;
3134 if (config->format == AUDIO_FORMAT_DEFAULT)
3135 config->format = AUDIO_FORMAT_PCM_16_BIT;
3136 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3137 config->format = AUDIO_FORMAT_PCM_16_BIT;
3138 ret = -EINVAL;
3139 goto error_open;
3140 }
3141 out->format = config->format;
3142 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3143 out->config = pcm_config_afe_proxy_playback;
3144 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003145 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3146 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3147 out->config = pcm_config_low_latency;
3148 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003149 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003150 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3152 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003154 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3155 format = AUDIO_FORMAT_PCM_16_BIT;
3156 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3157 out->config = pcm_config_deep_buffer;
3158 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003159 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003160 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003161 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003162 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003163 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003164 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 }
3166
Amit Shekhar1d896042014-10-03 13:16:09 -07003167 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3168 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003169 /* TODO remove this hardcoding and check why width is zero*/
3170 if (out->bit_width == 0)
3171 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003172 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3173 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003174 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303175 out->bit_width, out->channel_mask,
3176 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003177 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3178 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3179 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003180 if(adev->primary_output == NULL)
3181 adev->primary_output = out;
3182 else {
3183 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003184 ret = -EEXIST;
3185 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003186 }
3187 }
3188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 /* Check if this usecase is already existing */
3190 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003191 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3192 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003195 ret = -EEXIST;
3196 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 }
3198 pthread_mutex_unlock(&adev->lock);
3199
3200 out->stream.common.get_sample_rate = out_get_sample_rate;
3201 out->stream.common.set_sample_rate = out_set_sample_rate;
3202 out->stream.common.get_buffer_size = out_get_buffer_size;
3203 out->stream.common.get_channels = out_get_channels;
3204 out->stream.common.get_format = out_get_format;
3205 out->stream.common.set_format = out_set_format;
3206 out->stream.common.standby = out_standby;
3207 out->stream.common.dump = out_dump;
3208 out->stream.common.set_parameters = out_set_parameters;
3209 out->stream.common.get_parameters = out_get_parameters;
3210 out->stream.common.add_audio_effect = out_add_audio_effect;
3211 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3212 out->stream.get_latency = out_get_latency;
3213 out->stream.set_volume = out_set_volume;
3214 out->stream.write = out_write;
3215 out->stream.get_render_position = out_get_render_position;
3216 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003217 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003220 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003221 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222
3223 config->format = out->stream.common.get_format(&out->stream.common);
3224 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3225 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3226
3227 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303228 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003229 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003230
3231 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3232 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3233 popcount(out->channel_mask), out->playback_started);
3234
Eric Laurent994a6932013-07-17 11:51:42 -07003235 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003237
3238error_open:
3239 free(out);
3240 *stream_out = NULL;
3241 ALOGD("%s: exit: ret %d", __func__, ret);
3242 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243}
3244
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003245static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246 struct audio_stream_out *stream)
3247{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003248 struct stream_out *out = (struct stream_out *)stream;
3249 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003250 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303252 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3253
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003254 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303255 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003256 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303257 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003258 if(ret != 0)
3259 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3260 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003261 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003262 out_standby(&stream->common);
3263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003264 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003265 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003266 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003267 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 if (out->compr_config.codec != NULL)
3269 free(out->compr_config.codec);
3270 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003271
3272 if (adev->voice_tx_output == out)
3273 adev->voice_tx_output = NULL;
3274
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275 pthread_cond_destroy(&out->cond);
3276 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003278 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279}
3280
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003281static void close_compress_sessions(struct audio_device *adev)
3282{
Mingming Yin7b762e72015-03-04 13:47:32 -08003283 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303284 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003285 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003286 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303287
3288 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003289 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303290 if (is_offload_usecase(usecase->id)) {
3291 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003292 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3293 out = usecase->stream.out;
3294 pthread_mutex_unlock(&adev->lock);
3295 out_standby(&out->stream.common);
3296 pthread_mutex_lock(&adev->lock);
3297 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303298 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003299 }
3300 pthread_mutex_unlock(&adev->lock);
3301}
3302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3304{
3305 struct audio_device *adev = (struct audio_device *)dev;
3306 struct str_parms *parms;
3307 char *str;
3308 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003309 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003310 int ret;
3311 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003313 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303316 if (!parms)
3317 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003318 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3319 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303320 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303321 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303322 struct listnode *node;
3323 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303324 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303325 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003326 //close compress sessions on OFFLINE status
3327 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303328 } else if (strstr(snd_card_status, "ONLINE")) {
3329 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303330 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003331 //send dts hpx license if enabled
3332 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303333 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303334 }
3335
3336 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003337 status = voice_set_parameters(adev, parms);
3338 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003339 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003341 status = platform_set_parameters(adev->platform, parms);
3342 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003343 goto done;
3344
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003345 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3346 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003347 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3349 adev->bluetooth_nrec = true;
3350 else
3351 adev->bluetooth_nrec = false;
3352 }
3353
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003354 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3355 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3357 adev->screen_off = false;
3358 else
3359 adev->screen_off = true;
3360 }
3361
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003362 ret = str_parms_get_int(parms, "rotation", &val);
3363 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003364 bool reverse_speakers = false;
3365 switch(val) {
3366 // FIXME: note that the code below assumes that the speakers are in the correct placement
3367 // relative to the user when the device is rotated 90deg from its default rotation. This
3368 // assumption is device-specific, not platform-specific like this code.
3369 case 270:
3370 reverse_speakers = true;
3371 break;
3372 case 0:
3373 case 90:
3374 case 180:
3375 break;
3376 default:
3377 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003378 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003379 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003380 if (status == 0) {
3381 if (adev->speaker_lr_swap != reverse_speakers) {
3382 adev->speaker_lr_swap = reverse_speakers;
3383 // only update the selected device if there is active pcm playback
3384 struct audio_usecase *usecase;
3385 struct listnode *node;
3386 list_for_each(node, &adev->usecase_list) {
3387 usecase = node_to_item(node, struct audio_usecase, list);
3388 if (usecase->type == PCM_PLAYBACK) {
3389 select_devices(adev, usecase->id);
3390 break;
3391 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003392 }
3393 }
3394 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003395 }
3396
Mingming Yin514a8bc2014-07-29 15:22:21 -07003397 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3398 if (ret >= 0) {
3399 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3400 adev->bt_wb_speech_enabled = true;
3401 else
3402 adev->bt_wb_speech_enabled = false;
3403 }
3404
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003405 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3406 if (ret >= 0) {
3407 val = atoi(value);
3408 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3409 ALOGV("cache new edid");
3410 platform_cache_edid(adev->platform);
3411 }
3412 }
3413
3414 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3415 if (ret >= 0) {
3416 val = atoi(value);
3417 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3418 ALOGV("invalidate cached edid");
3419 platform_invalidate_edid(adev->platform);
3420 }
3421 }
3422
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003423 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003424
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003425done:
3426 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003427 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303428error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003429 ALOGV("%s: exit with code(%d)", __func__, status);
3430 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431}
3432
3433static char* adev_get_parameters(const struct audio_hw_device *dev,
3434 const char *keys)
3435{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003436 struct audio_device *adev = (struct audio_device *)dev;
3437 struct str_parms *reply = str_parms_create();
3438 struct str_parms *query = str_parms_create_str(keys);
3439 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303440 char value[256] = {0};
3441 int ret = 0;
3442
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003443 if (!query || !reply) {
3444 ALOGE("adev_get_parameters: failed to create query or reply");
3445 return NULL;
3446 }
3447
Naresh Tannirud7205b62014-06-20 02:54:48 +05303448 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3449 sizeof(value));
3450 if (ret >=0) {
3451 int val = 1;
3452 pthread_mutex_lock(&adev->snd_card_status.lock);
3453 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3454 val = 0;
3455 pthread_mutex_unlock(&adev->snd_card_status.lock);
3456 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3457 goto exit;
3458 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003459
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003460 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003461 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003462 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003463 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303464 pthread_mutex_unlock(&adev->lock);
3465
Naresh Tannirud7205b62014-06-20 02:54:48 +05303466exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003467 str = str_parms_to_str(reply);
3468 str_parms_destroy(query);
3469 str_parms_destroy(reply);
3470
3471 ALOGV("%s: exit: returns - %s", __func__, str);
3472 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473}
3474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003475static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476{
3477 return 0;
3478}
3479
3480static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3481{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003482 int ret;
3483 struct audio_device *adev = (struct audio_device *)dev;
3484 pthread_mutex_lock(&adev->lock);
3485 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003486 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003487 pthread_mutex_unlock(&adev->lock);
3488 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489}
3490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003491static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3492 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493{
3494 return -ENOSYS;
3495}
3496
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003497static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3498 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499{
3500 return -ENOSYS;
3501}
3502
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003503static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3504 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505{
3506 return -ENOSYS;
3507}
3508
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003509static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3510 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511{
3512 return -ENOSYS;
3513}
3514
3515static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3516{
3517 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 pthread_mutex_lock(&adev->lock);
3520 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003523 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3524 voice_is_in_call(adev)) {
3525 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003526 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003527 adev->current_call_output = NULL;
3528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 }
3530 pthread_mutex_unlock(&adev->lock);
3531 return 0;
3532}
3533
3534static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3535{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003536 int ret;
3537
3538 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003539 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003540 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3541 pthread_mutex_unlock(&adev->lock);
3542
3543 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544}
3545
3546static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3547{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003548 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 return 0;
3550}
3551
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003552static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 const struct audio_config *config)
3554{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003555 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003557 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3558 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559}
3560
3561static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003562 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 audio_devices_t devices,
3564 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003565 struct audio_stream_in **stream_in,
3566 audio_input_flags_t flags __unused,
3567 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003568 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569{
3570 struct audio_device *adev = (struct audio_device *)dev;
3571 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003572 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003573 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003574 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 *stream_in = NULL;
3577 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3578 return -EINVAL;
3579
3580 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003581
3582 if (!in) {
3583 ALOGE("failed to allocate input stream");
3584 return -ENOMEM;
3585 }
3586
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303587 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003588 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3589 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003591 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003592 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 in->stream.common.get_sample_rate = in_get_sample_rate;
3595 in->stream.common.set_sample_rate = in_set_sample_rate;
3596 in->stream.common.get_buffer_size = in_get_buffer_size;
3597 in->stream.common.get_channels = in_get_channels;
3598 in->stream.common.get_format = in_get_format;
3599 in->stream.common.set_format = in_set_format;
3600 in->stream.common.standby = in_standby;
3601 in->stream.common.dump = in_dump;
3602 in->stream.common.set_parameters = in_set_parameters;
3603 in->stream.common.get_parameters = in_get_parameters;
3604 in->stream.common.add_audio_effect = in_add_audio_effect;
3605 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3606 in->stream.set_gain = in_set_gain;
3607 in->stream.read = in_read;
3608 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3609
3610 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003611 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 in->standby = 1;
3614 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003615 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003616 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617
3618 /* Update config params with the requested sample rate and channels */
3619 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003620 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3621 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3622 is_low_latency = true;
3623#if LOW_LATENCY_CAPTURE_USE_CASE
3624 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3625#endif
3626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003629 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003631 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303632 if (adev->mode != AUDIO_MODE_IN_CALL) {
3633 ret = -EINVAL;
3634 goto err_open;
3635 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003636 if (config->sample_rate == 0)
3637 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3638 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3639 config->sample_rate != 8000) {
3640 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3641 ret = -EINVAL;
3642 goto err_open;
3643 }
3644 if (config->format == AUDIO_FORMAT_DEFAULT)
3645 config->format = AUDIO_FORMAT_PCM_16_BIT;
3646 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3647 config->format = AUDIO_FORMAT_PCM_16_BIT;
3648 ret = -EINVAL;
3649 goto err_open;
3650 }
3651
3652 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3653 in->config = pcm_config_afe_proxy_record;
3654 in->config.channels = channel_count;
3655 in->config.rate = config->sample_rate;
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003656 } else if (audio_extn_ssr_get_enabled() &&
3657 ((channel_count == 2) || (channel_count == 6)) &&
3658 ((AUDIO_SOURCE_MIC == source) || (AUDIO_SOURCE_CAMCORDER == source))) {
3659 ALOGD("%s: Found SSR use case starting SSR lib with channel_count :%d",
3660 __func__, channel_count);
3661 if (audio_extn_ssr_init(in, channel_count)) {
3662 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3663 if (channel_count == 2) {
3664 ALOGD("%s: falling back to default record usecase", __func__);
3665 in->config.channels = channel_count;
3666 frame_size = audio_stream_in_frame_size(&in->stream);
3667 buffer_size = get_input_buffer_size(config->sample_rate,
3668 config->format,
3669 channel_count,
3670 is_low_latency);
3671 in->config.period_size = buffer_size / frame_size;
3672 } else {
3673 ALOGD("%s: unable to start SSR record session for 6 channel input", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003674 ret = -EINVAL;
3675 goto err_open;
3676 }
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003677 }
Mingming Yine62d7842013-10-25 16:26:03 -07003678 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003679 audio_extn_compr_cap_format_supported(config->format) &&
3680 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003681 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003682 } else {
3683 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003684 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003685 buffer_size = get_input_buffer_size(config->sample_rate,
3686 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003687 channel_count,
3688 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003689 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003690 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3691 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3692 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3693 (in->config.rate == 8000 || in->config.rate == 16000) &&
3694 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3695 voice_extn_compress_voip_open_input_stream(in);
3696 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003699 /* This stream could be for sound trigger lab,
3700 get sound trigger pcm if present */
3701 audio_extn_sound_trigger_check_and_get_session(in);
3702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003704 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003705 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
3707err_open:
3708 free(in);
3709 *stream_in = NULL;
3710 return ret;
3711}
3712
3713static void adev_close_input_stream(struct audio_hw_device *dev,
3714 struct audio_stream_in *stream)
3715{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003716 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003717 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003718 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303719
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303720 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003721
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303722 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003723 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303724
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003725 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303726 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003727 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303728 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003729 if (ret != 0)
3730 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3731 __func__, ret);
3732 } else
3733 in_standby(&stream->common);
3734
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003735 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003736 audio_extn_ssr_deinit();
3737 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738
Mingming Yine62d7842013-10-25 16:26:03 -07003739 if(audio_extn_compr_cap_enabled() &&
3740 audio_extn_compr_cap_format_supported(in->config.format))
3741 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003742
3743 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 return;
3745}
3746
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003747static int adev_dump(const audio_hw_device_t *device __unused,
3748 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749{
3750 return 0;
3751}
3752
3753static int adev_close(hw_device_t *device)
3754{
3755 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003756
3757 if (!adev)
3758 return 0;
3759
3760 pthread_mutex_lock(&adev_init_lock);
3761
3762 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003763 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003764 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003765 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003766 audio_route_free(adev->audio_route);
3767 free(adev->snd_dev_ref_cnt);
3768 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003769 if (adev->adm_deinit)
3770 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003771 free(device);
3772 adev = NULL;
3773 }
3774 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 return 0;
3777}
3778
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003779/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3780 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3781 * just that it _might_ work.
3782 */
3783static int period_size_is_plausible_for_low_latency(int period_size)
3784{
3785 switch (period_size) {
3786 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003787 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003788 case 240:
3789 case 320:
3790 case 480:
3791 return 1;
3792 default:
3793 return 0;
3794 }
3795}
3796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797static int adev_open(const hw_module_t *module, const char *name,
3798 hw_device_t **device)
3799{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003800 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003802 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3804
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003805 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003806 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003807 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003808 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003809 ALOGD("%s: returning existing instance of adev", __func__);
3810 ALOGD("%s: exit", __func__);
3811 pthread_mutex_unlock(&adev_init_lock);
3812 return 0;
3813 }
3814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815 adev = calloc(1, sizeof(struct audio_device));
3816
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003817 if (!adev) {
3818 pthread_mutex_unlock(&adev_init_lock);
3819 return -ENOMEM;
3820 }
3821
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003822 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3825 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3826 adev->device.common.module = (struct hw_module_t *)module;
3827 adev->device.common.close = adev_close;
3828
3829 adev->device.init_check = adev_init_check;
3830 adev->device.set_voice_volume = adev_set_voice_volume;
3831 adev->device.set_master_volume = adev_set_master_volume;
3832 adev->device.get_master_volume = adev_get_master_volume;
3833 adev->device.set_master_mute = adev_set_master_mute;
3834 adev->device.get_master_mute = adev_get_master_mute;
3835 adev->device.set_mode = adev_set_mode;
3836 adev->device.set_mic_mute = adev_set_mic_mute;
3837 adev->device.get_mic_mute = adev_get_mic_mute;
3838 adev->device.set_parameters = adev_set_parameters;
3839 adev->device.get_parameters = adev_get_parameters;
3840 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3841 adev->device.open_output_stream = adev_open_output_stream;
3842 adev->device.close_output_stream = adev_close_output_stream;
3843 adev->device.open_input_stream = adev_open_input_stream;
3844 adev->device.close_input_stream = adev_close_input_stream;
3845 adev->device.dump = adev_dump;
3846
3847 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003849 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003850 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003853 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003854 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003855 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003856 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003857 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003858 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003859 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303860 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303861 adev->perf_lock_opts[0] = 0x101;
3862 adev->perf_lock_opts[1] = 0x20E;
3863 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303864
3865 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3866 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003868 adev->platform = platform_init(adev);
3869 if (!adev->platform) {
3870 free(adev->snd_dev_ref_cnt);
3871 free(adev);
3872 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3873 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003874 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003875 return -EINVAL;
3876 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003877
Naresh Tanniru4c630392014-05-12 01:05:52 +05303878 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3879
Eric Laurentc4aef752013-09-12 17:45:53 -07003880 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3881 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3882 if (adev->visualizer_lib == NULL) {
3883 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3884 } else {
3885 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3886 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003887 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003888 "visualizer_hal_start_output");
3889 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003890 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003891 "visualizer_hal_stop_output");
3892 }
3893 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003894 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003895 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003896
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003897 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3898 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3899 if (adev->offload_effects_lib == NULL) {
3900 ALOGE("%s: DLOPEN failed for %s", __func__,
3901 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3902 } else {
3903 ALOGV("%s: DLOPEN successful for %s", __func__,
3904 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3905 adev->offload_effects_start_output =
3906 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3907 "offload_effects_bundle_hal_start_output");
3908 adev->offload_effects_stop_output =
3909 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3910 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003911 adev->offload_effects_set_hpx_state =
3912 (int (*)(bool))dlsym(adev->offload_effects_lib,
3913 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303914 adev->offload_effects_get_parameters =
3915 (void (*)(struct str_parms *, struct str_parms *))
3916 dlsym(adev->offload_effects_lib,
3917 "offload_effects_bundle_get_parameters");
3918 adev->offload_effects_set_parameters =
3919 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3920 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003921 }
3922 }
3923
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003924 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3925 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3926 if (adev->adm_lib == NULL) {
3927 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3928 } else {
3929 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3930 adev->adm_init = (adm_init_t)
3931 dlsym(adev->adm_lib, "adm_init");
3932 adev->adm_deinit = (adm_deinit_t)
3933 dlsym(adev->adm_lib, "adm_deinit");
3934 adev->adm_register_input_stream = (adm_register_input_stream_t)
3935 dlsym(adev->adm_lib, "adm_register_input_stream");
3936 adev->adm_register_output_stream = (adm_register_output_stream_t)
3937 dlsym(adev->adm_lib, "adm_register_output_stream");
3938 adev->adm_deregister_stream = (adm_deregister_stream_t)
3939 dlsym(adev->adm_lib, "adm_deregister_stream");
3940 adev->adm_request_focus = (adm_request_focus_t)
3941 dlsym(adev->adm_lib, "adm_request_focus");
3942 adev->adm_abandon_focus = (adm_abandon_focus_t)
3943 dlsym(adev->adm_lib, "adm_abandon_focus");
3944 }
3945 }
3946
Mingming Yin514a8bc2014-07-29 15:22:21 -07003947 adev->bt_wb_speech_enabled = false;
3948
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003949 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950 *device = &adev->device.common;
3951
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003952 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3953 &adev->streams_output_cfg_list);
3954
Kiran Kandi910e1862013-10-29 13:29:42 -07003955 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003956
3957 char value[PROPERTY_VALUE_MAX];
3958 int trial;
3959 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3960 trial = atoi(value);
3961 if (period_size_is_plausible_for_low_latency(trial)) {
3962 pcm_config_low_latency.period_size = trial;
3963 pcm_config_low_latency.start_threshold = trial / 4;
3964 pcm_config_low_latency.avail_min = trial / 4;
3965 configured_low_latency_capture_period_size = trial;
3966 }
3967 }
3968 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3969 trial = atoi(value);
3970 if (period_size_is_plausible_for_low_latency(trial)) {
3971 configured_low_latency_capture_period_size = trial;
3972 }
3973 }
3974
vivek mehta446c3962015-09-14 10:57:35 -07003975 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003976 pthread_mutex_unlock(&adev_init_lock);
3977
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003978 if (adev->adm_init)
3979 adev->adm_data = adev->adm_init();
3980
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303981 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07003982 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983 return 0;
3984}
3985
3986static struct hw_module_methods_t hal_module_methods = {
3987 .open = adev_open,
3988};
3989
3990struct audio_module HAL_MODULE_INFO_SYM = {
3991 .common = {
3992 .tag = HARDWARE_MODULE_TAG,
3993 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3994 .hal_api_version = HARDWARE_HAL_API_VERSION,
3995 .id = AUDIO_HARDWARE_MODULE_ID,
3996 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003997 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 .methods = &hal_module_methods,
3999 },
4000};