blob: d7a3169cc8f9ef86a859e391448f7db94feea410 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530508
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700509 if (audio_extn_spkr_prot_is_enabled())
510 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 /* start usb playback thread */
512 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
513 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
514 audio_extn_usb_start_playback(adev);
515
516 /* start usb capture thread */
517 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
518 audio_extn_usb_start_capture(adev);
519
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800520 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
521 audio_extn_spkr_prot_is_enabled()) {
522 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 adev->snd_dev_ref_cnt[snd_device]--;
524 return -EINVAL;
525 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200526 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800527 if (audio_extn_spkr_prot_start_processing(snd_device)) {
528 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200529 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800530 return -EINVAL;
531 }
532 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700533 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700534 /* due to the possibility of calibration overwrite between listen
535 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700540 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 return -EINVAL;
547 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300548 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700549 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530550
551 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
552 !adev->native_playback_enabled &&
553 audio_is_true_native_stream_active(adev)) {
554 ALOGD("%s: %d: napb: enabling native mode in hardware",
555 __func__, __LINE__);
556 audio_route_apply_and_update_path(adev->audio_route,
557 "true-native-mode");
558 adev->native_playback_enabled = true;
559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 return 0;
562}
563
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700564int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700565 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
568
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 if (snd_device < SND_DEVICE_MIN ||
570 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800571 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800572 return -EINVAL;
573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
575 ALOGE("%s: device ref cnt is already 0", __func__);
576 return -EINVAL;
577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700580
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
582 ALOGE("%s: Invalid sound device returned", __func__);
583 return -EINVAL;
584 }
585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700587 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800588 /* exit usb play back thread */
589 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
590 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
591 audio_extn_usb_stop_playback();
592
593 /* exit usb capture thread */
594 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700595 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800596
597 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ashish Jain81eb2a82015-05-13 10:52:34 +0530604 if (snd_device == SND_DEVICE_OUT_HDMI)
605 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530606 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
607 adev->native_playback_enabled) {
608 ALOGD("%s: %d: napb: disabling native mode in hardware",
609 __func__, __LINE__);
610 audio_route_reset_and_update_path(adev->audio_route,
611 "true-native-mode");
612 adev->native_playback_enabled = false;
613 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530614
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200615 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700616 audio_extn_sound_trigger_update_device_status(snd_device,
617 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530618 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800619 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622 return 0;
623}
624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625static void check_usecases_codec_backend(struct audio_device *adev,
626 struct audio_usecase *uc_info,
627 snd_device_t snd_device)
628{
629 struct listnode *node;
630 struct audio_usecase *usecase;
631 bool switch_device[AUDIO_USECASE_MAX];
632 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800633 int backend_idx = DEFAULT_CODEC_BACKEND;
634 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635
636 /*
637 * This function is to make sure that all the usecases that are active on
638 * the hardware codec backend are always routed to any one device that is
639 * handled by the hardware codec.
640 * For example, if low-latency and deep-buffer usecases are currently active
641 * on speaker and out_set_parameters(headset) is received on low-latency
642 * output, then we have to make sure deep-buffer is also switched to headset,
643 * because of the limitation that both the devices cannot be enabled
644 * at the same time as they share the same backend.
645 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700646 /*
647 * This call is to check if we need to force routing for a particular stream
648 * If there is a backend configuration change for the device when a
649 * new stream starts, then ADM needs to be closed and re-opened with the new
650 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700652 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
654 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530655
656 ALOGD("%s:becf: force routing %d", __func__, force_routing);
657
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800660 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800661 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 for (i = 0; i < AUDIO_USECASE_MAX; i++)
663 switch_device[i] = false;
664
665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667
668 if (usecase == uc_info)
669 continue;
670 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
673 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
674 __func__, i, backend_idx, usecase_backend_idx,
675 platform_get_snd_device_name(snd_device),
676 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800677
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800678 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700679 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800680 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
681 usecase_backend_idx == backend_idx) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530682 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
683 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700684 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 switch_device[usecase->id] = true;
687 num_uc_to_switch++;
688 }
689 }
690
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
692 num_uc_to_switch);
693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530697 /* Make sure the previous devices to be disabled first and then enable the
698 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 list_for_each(node, &adev->usecase_list) {
700 usecase = node_to_item(node, struct audio_usecase, list);
701 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
704 }
705
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
708 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700710 }
711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 /* Re-route all the usecases on the shared backend other than the
714 specified usecase to new snd devices */
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530717 /* Update the out_snd_device only before enabling the audio route */
718 if (switch_device[usecase->id]) {
719 usecase->out_snd_device = snd_device;
720 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530721 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530722 use_case_table[usecase->id],
723 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530724 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728 }
729}
730
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731static void check_and_route_capture_usecases(struct audio_device *adev,
732 struct audio_usecase *uc_info,
733 snd_device_t snd_device)
734{
735 struct listnode *node;
736 struct audio_usecase *usecase;
737 bool switch_device[AUDIO_USECASE_MAX];
738 int i, num_uc_to_switch = 0;
739
740 /*
741 * This function is to make sure that all the active capture usecases
742 * are always routed to the same input sound device.
743 * For example, if audio-record and voice-call usecases are currently
744 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
745 * is received for voice call then we have to make sure that audio-record
746 * usecase is also switched to earpiece i.e. voice-dmic-ef,
747 * because of the limitation that two devices cannot be enabled
748 * at the same time if they share the same backend.
749 */
750 for (i = 0; i < AUDIO_USECASE_MAX; i++)
751 switch_device[i] = false;
752
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800755 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700757 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700758 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530759 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
760 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700761 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
763 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700764 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700765 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 switch_device[usecase->id] = true;
767 num_uc_to_switch++;
768 }
769 }
770
771 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700772 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700773
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530774 /* Make sure the previous devices to be disabled first and then enable the
775 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 list_for_each(node, &adev->usecase_list) {
777 usecase = node_to_item(node, struct audio_usecase, list);
778 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700779 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800780 }
781 }
782
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
785 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700786 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 }
788 }
789
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700790 /* Re-route all the usecases on the shared backend other than the
791 specified usecase to new snd devices */
792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
794 /* Update the in_snd_device only before enabling the audio route */
795 if (switch_device[usecase->id] ) {
796 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800797 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530798 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 }
800 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700801 }
802}
803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700805static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700807 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700808 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809
810 switch (channels) {
811 /*
812 * Do not handle stereo output in Multi-channel cases
813 * Stereo case is handled in normal playback path
814 */
815 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700816 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
819 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
820 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
821 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800822 break;
823 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700824 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
828 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
829 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
830 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800831 break;
832 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700833 ALOGE("HDMI does not support multi channel playback");
834 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835 break;
836 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700837 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800838}
839
Alexy Josephb1379942016-01-29 15:49:38 -0800840audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800841 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842{
843 struct audio_usecase *usecase;
844 struct listnode *node;
845
846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800848 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700849 ALOGV("%s: usecase id %d", __func__, usecase->id);
850 return usecase->id;
851 }
852 }
853 return USECASE_INVALID;
854}
855
Alexy Josephb1379942016-01-29 15:49:38 -0800856struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700857 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858{
859 struct audio_usecase *usecase;
860 struct listnode *node;
861
862 list_for_each(node, &adev->usecase_list) {
863 usecase = node_to_item(node, struct audio_usecase, list);
864 if (usecase->id == uc_id)
865 return usecase;
866 }
867 return NULL;
868}
869
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530870/*
871 * is a true native playback active
872 */
873bool audio_is_true_native_stream_active(struct audio_device *adev)
874{
875 bool active = false;
876 int i = 0;
877 struct listnode *node;
878
879 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
880 ALOGV("%s:napb: not in true mode or non hdphones device",
881 __func__);
882 active = false;
883 goto exit;
884 }
885
886 list_for_each(node, &adev->usecase_list) {
887 struct audio_usecase *uc;
888 uc = node_to_item(node, struct audio_usecase, list);
889 struct stream_out *curr_out =
890 (struct stream_out*) uc->stream.out;
891
892 if (curr_out && PCM_PLAYBACK == uc->type) {
893 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
894 "(%d) device %s", __func__, i++, use_case_table[uc->id],
895 uc->id, curr_out->sample_rate,
896 curr_out->bit_width,
897 platform_get_snd_device_name(uc->out_snd_device));
898
899 if (is_offload_usecase(uc->id) &&
900 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
901 active = true;
902 ALOGD("%s:napb:native stream detected", __func__);
903 }
904 }
905 }
906exit:
907 return active;
908}
909
910
911static bool force_device_switch(struct audio_usecase *usecase)
912{
913 bool ret = false;
914 bool is_it_true_mode = false;
915
916 if (is_offload_usecase(usecase->id) &&
917 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800918 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
919 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
920 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530921 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
922 if ((is_it_true_mode && !adev->native_playback_enabled) ||
923 (!is_it_true_mode && adev->native_playback_enabled)){
924 ret = true;
925 ALOGD("napb: time to toggle native mode");
926 }
927 }
928
929 return ret;
930}
931
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700932int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800934 snd_device_t out_snd_device = SND_DEVICE_NONE;
935 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700936 struct audio_usecase *usecase = NULL;
937 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800938 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800939 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800940 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800941 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800943
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530944 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
945
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 usecase = get_usecase_from_list(adev, uc_id);
947 if (usecase == NULL) {
948 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
949 return -EINVAL;
950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800952 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800953 (usecase->type == VOIP_CALL) ||
954 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700955 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800956 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700957 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958 usecase->devices = usecase->stream.out->devices;
959 } else {
960 /*
961 * If the voice call is active, use the sound devices of voice call usecase
962 * so that it would not result any device switch. All the usecases will
963 * be switched to new device when select_devices() is called for voice call
964 * usecase. This is to avoid switching devices for voice call when
965 * check_usecases_codec_backend() is called below.
966 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800967 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700968 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800969 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700970 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
971 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972 in_snd_device = vc_usecase->in_snd_device;
973 out_snd_device = vc_usecase->out_snd_device;
974 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800975 } else if (voice_extn_compress_voip_is_active(adev)) {
976 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700977 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530978 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700979 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800980 in_snd_device = voip_usecase->in_snd_device;
981 out_snd_device = voip_usecase->out_snd_device;
982 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800983 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800984 hfp_ucid = audio_extn_hfp_get_usecase();
985 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700986 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800987 in_snd_device = hfp_usecase->in_snd_device;
988 out_snd_device = hfp_usecase->out_snd_device;
989 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 }
991 if (usecase->type == PCM_PLAYBACK) {
992 usecase->devices = usecase->stream.out->devices;
993 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700994 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700995 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800996 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700997 if (usecase->stream.out == adev->primary_output &&
998 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800999 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001000 select_devices(adev, adev->active_input->usecase);
1001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 } else if (usecase->type == PCM_CAPTURE) {
1004 usecase->devices = usecase->stream.in->device;
1005 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001006 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001007 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001008 if (adev->active_input &&
1009 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301010 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1011 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1012 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001013 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001014 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001015 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1016 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001017 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001018 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001019 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 }
1021 }
1022
1023 if (out_snd_device == usecase->out_snd_device &&
1024 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301025
1026 if (!force_device_switch(usecase))
1027 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 }
1029
sangwoobc677242013-08-08 16:53:43 +09001030 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device, platform_get_snd_device_name(out_snd_device),
1032 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 /*
1035 * Limitation: While in call, to do a device switch we need to disable
1036 * and enable both RX and TX devices though one of them is same as current
1037 * device.
1038 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001039 if ((usecase->type == VOICE_CALL) &&
1040 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1041 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001042 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001043 }
1044
1045 if (((usecase->type == VOICE_CALL) ||
1046 (usecase->type == VOIP_CALL)) &&
1047 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1048 /* Disable sidetone only if voice/voip call already exists */
1049 if (voice_is_call_state_active(adev) ||
1050 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001051 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001052 }
1053
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 /* Disable current sound devices */
1055 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001056 disable_audio_route(adev, usecase);
1057 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 }
1059
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001061 disable_audio_route(adev, usecase);
1062 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 }
1064
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001065 /* Applicable only on the targets that has external modem.
1066 * New device information should be sent to modem before enabling
1067 * the devices to reduce in-call device switch time.
1068 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001069 if ((usecase->type == VOICE_CALL) &&
1070 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1071 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001072 status = platform_switch_voice_call_enable_device_config(adev->platform,
1073 out_snd_device,
1074 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001075 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001076
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 /* Enable new sound devices */
1078 if (out_snd_device != SND_DEVICE_NONE) {
1079 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1080 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001081 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 }
1083
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 if (in_snd_device != SND_DEVICE_NONE) {
1085 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001087 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088
Avinash Vaish71a8b972014-07-24 15:36:33 +05301089 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001090 status = platform_switch_voice_call_device_post(adev->platform,
1091 out_snd_device,
1092 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301093 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001094 /* Enable sidetone only if voice/voip call already exists */
1095 if (voice_is_call_state_active(adev) ||
1096 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001097 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301098 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001099
sangwoo170731f2013-06-08 15:36:36 +09001100 usecase->in_snd_device = in_snd_device;
1101 usecase->out_snd_device = out_snd_device;
1102
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301103 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001104 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301105 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001106 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301107 usecase->stream.out->flags,
1108 usecase->stream.out->format,
1109 usecase->stream.out->sample_rate,
1110 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301111 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301112 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001113 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301114 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001115
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001116 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001117
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001118 /* Applicable only on the targets that has external modem.
1119 * Enable device command should be sent to modem only after
1120 * enabling voice call mixer controls
1121 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001122 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001123 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1124 out_snd_device,
1125 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301126 ALOGD("%s: done",__func__);
1127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128 return status;
1129}
1130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131static int stop_input_stream(struct stream_in *in)
1132{
1133 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 struct audio_usecase *uc_info;
1135 struct audio_device *adev = in->dev;
1136
Eric Laurentc8400632013-02-14 19:04:54 -08001137 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138
Eric Laurent994a6932013-07-17 11:51:42 -07001139 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 uc_info = get_usecase_from_list(adev, in->usecase);
1142 if (uc_info == NULL) {
1143 ALOGE("%s: Could not find the usecase (%d) in the list",
1144 __func__, in->usecase);
1145 return -EINVAL;
1146 }
1147
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001148 /* Close in-call recording streams */
1149 voice_check_and_stop_incall_rec_usecase(adev, in);
1150
Eric Laurent150dbfe2013-02-27 14:31:02 -08001151 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001152 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153
1154 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001155 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001157 list_remove(&uc_info->list);
1158 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159
Eric Laurent994a6932013-07-17 11:51:42 -07001160 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161 return ret;
1162}
1163
1164int start_input_stream(struct stream_in *in)
1165{
1166 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001167 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 struct audio_usecase *uc_info;
1169 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301170 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171
Mingming Yin2664a5b2015-09-03 10:53:11 -07001172 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1173 if (get_usecase_from_list(adev, usecase) == NULL)
1174 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301175 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1176 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001177
Naresh Tanniru80659832014-06-04 18:17:56 +05301178
1179 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301180 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301181 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301182 goto error_config;
1183 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301184
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001185 /* Check if source matches incall recording usecase criteria */
1186 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1187 if (ret)
1188 goto error_config;
1189 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001190 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1191
1192 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1193 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1194 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1195 goto error_config;
1196 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001197
Eric Laurentb23d5282013-05-14 15:27:20 -07001198 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 if (in->pcm_device_id < 0) {
1200 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1201 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001202 ret = -EINVAL;
1203 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001205
1206 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001208
1209 if (!uc_info) {
1210 ret = -ENOMEM;
1211 goto error_config;
1212 }
1213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214 uc_info->id = in->usecase;
1215 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001216 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217 uc_info->devices = in->device;
1218 uc_info->in_snd_device = SND_DEVICE_NONE;
1219 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001221 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301222 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1223 adev->perf_lock_opts,
1224 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226
Eric Laurentc8400632013-02-14 19:04:54 -08001227 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001228 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1229
1230 unsigned int flags = PCM_IN;
1231 unsigned int pcm_open_retry_count = 0;
1232
1233 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1234 flags |= PCM_MMAP | PCM_NOIRQ;
1235 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1236 }
1237
1238 while (1) {
1239 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1240 flags, &in->config);
1241 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1242 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1243 if (in->pcm != NULL) {
1244 pcm_close(in->pcm);
1245 in->pcm = NULL;
1246 }
1247 if (pcm_open_retry_count-- == 0) {
1248 ret = -EIO;
1249 goto error_open;
1250 }
1251 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1252 continue;
1253 }
1254 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001255 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001256
1257 ALOGV("%s: pcm_prepare", __func__);
1258 ret = pcm_prepare(in->pcm);
1259 if (ret < 0) {
1260 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1261 pcm_close(in->pcm);
1262 in->pcm = NULL;
1263 goto error_open;
1264 }
1265
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301266 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001267 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001268
Eric Laurentc8400632013-02-14 19:04:54 -08001269 return ret;
1270
1271error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301272 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001274error_config:
1275 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301276 /*
1277 * sleep 50ms to allow sufficient time for kernel
1278 * drivers to recover incases like SSR.
1279 */
1280 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001282
1283 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284}
1285
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001286void lock_input_stream(struct stream_in *in)
1287{
1288 pthread_mutex_lock(&in->pre_lock);
1289 pthread_mutex_lock(&in->lock);
1290 pthread_mutex_unlock(&in->pre_lock);
1291}
1292
1293void lock_output_stream(struct stream_out *out)
1294{
1295 pthread_mutex_lock(&out->pre_lock);
1296 pthread_mutex_lock(&out->lock);
1297 pthread_mutex_unlock(&out->pre_lock);
1298}
1299
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300/* must be called with out->lock locked */
1301static int send_offload_cmd_l(struct stream_out* out, int command)
1302{
1303 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1304
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001305 if (!cmd) {
1306 ALOGE("failed to allocate mem for command 0x%x", command);
1307 return -ENOMEM;
1308 }
1309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 ALOGVV("%s %d", __func__, command);
1311
1312 cmd->cmd = command;
1313 list_add_tail(&out->offload_cmd_list, &cmd->node);
1314 pthread_cond_signal(&out->offload_cond);
1315 return 0;
1316}
1317
1318/* must be called iwth out->lock locked */
1319static void stop_compressed_output_l(struct stream_out *out)
1320{
1321 out->offload_state = OFFLOAD_STATE_IDLE;
1322 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001323 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001324 if (out->compr != NULL) {
1325 compress_stop(out->compr);
1326 while (out->offload_thread_blocked) {
1327 pthread_cond_wait(&out->cond, &out->lock);
1328 }
1329 }
1330}
1331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001332bool is_offload_usecase(audio_usecase_t uc_id)
1333{
1334 unsigned int i;
1335 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1336 if (uc_id == offload_usecases[i])
1337 return true;
1338 }
1339 return false;
1340}
1341
vivek mehta446c3962015-09-14 10:57:35 -07001342static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001343{
vivek mehta446c3962015-09-14 10:57:35 -07001344 audio_usecase_t ret_uc = USECASE_INVALID;
1345 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001346 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001347 if (!adev->multi_offload_enable) {
1348 if (is_direct_pcm)
1349 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1350 else
1351 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001352
vivek mehta446c3962015-09-14 10:57:35 -07001353 pthread_mutex_lock(&adev->lock);
1354 if (get_usecase_from_list(adev, ret_uc) != NULL)
1355 ret_uc = USECASE_INVALID;
1356 pthread_mutex_unlock(&adev->lock);
1357
1358 return ret_uc;
1359 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001360
1361 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001362 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1363 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1364 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1365 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001366 break;
1367 }
1368 }
vivek mehta446c3962015-09-14 10:57:35 -07001369
1370 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1371 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001372}
1373
1374static void free_offload_usecase(struct audio_device *adev,
1375 audio_usecase_t uc_id)
1376{
vivek mehta446c3962015-09-14 10:57:35 -07001377 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001378 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001379
1380 if (!adev->multi_offload_enable)
1381 return;
1382
1383 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1384 if (offload_usecases[offload_uc_index] == uc_id) {
1385 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001386 break;
1387 }
1388 }
1389 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1390}
1391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392static void *offload_thread_loop(void *context)
1393{
1394 struct stream_out *out = (struct stream_out *) context;
1395 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001396 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001397
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001398 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1399 set_sched_policy(0, SP_FOREGROUND);
1400 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1401
1402 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001403 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001404 for (;;) {
1405 struct offload_cmd *cmd = NULL;
1406 stream_callback_event_t event;
1407 bool send_callback = false;
1408
1409 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1410 __func__, list_empty(&out->offload_cmd_list),
1411 out->offload_state);
1412 if (list_empty(&out->offload_cmd_list)) {
1413 ALOGV("%s SLEEPING", __func__);
1414 pthread_cond_wait(&out->offload_cond, &out->lock);
1415 ALOGV("%s RUNNING", __func__);
1416 continue;
1417 }
1418
1419 item = list_head(&out->offload_cmd_list);
1420 cmd = node_to_item(item, struct offload_cmd, node);
1421 list_remove(item);
1422
1423 ALOGVV("%s STATE %d CMD %d out->compr %p",
1424 __func__, out->offload_state, cmd->cmd, out->compr);
1425
1426 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1427 free(cmd);
1428 break;
1429 }
1430
1431 if (out->compr == NULL) {
1432 ALOGE("%s: Compress handle is NULL", __func__);
1433 pthread_cond_signal(&out->cond);
1434 continue;
1435 }
1436 out->offload_thread_blocked = true;
1437 pthread_mutex_unlock(&out->lock);
1438 send_callback = false;
1439 switch(cmd->cmd) {
1440 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001441 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001442 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001443 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001444 send_callback = true;
1445 event = STREAM_CBK_EVENT_WRITE_READY;
1446 break;
1447 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001448 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301449 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001450 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301451 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001452 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301453 if (ret < 0)
1454 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301455 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301456 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001457 compress_drain(out->compr);
1458 else
1459 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301460 if (ret != -ENETRESET) {
1461 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301462 pthread_mutex_lock(&out->lock);
1463 out->send_new_metadata = 1;
1464 out->send_next_track_params = true;
1465 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301466 event = STREAM_CBK_EVENT_DRAIN_READY;
1467 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1468 } else
1469 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 break;
1471 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001472 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001474 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001475 send_callback = true;
1476 event = STREAM_CBK_EVENT_DRAIN_READY;
1477 break;
1478 default:
1479 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1480 break;
1481 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483 out->offload_thread_blocked = false;
1484 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001485 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001486 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001487 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001488 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001489 free(cmd);
1490 }
1491
1492 pthread_cond_signal(&out->cond);
1493 while (!list_empty(&out->offload_cmd_list)) {
1494 item = list_head(&out->offload_cmd_list);
1495 list_remove(item);
1496 free(node_to_item(item, struct offload_cmd, node));
1497 }
1498 pthread_mutex_unlock(&out->lock);
1499
1500 return NULL;
1501}
1502
1503static int create_offload_callback_thread(struct stream_out *out)
1504{
1505 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1506 list_init(&out->offload_cmd_list);
1507 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1508 offload_thread_loop, out);
1509 return 0;
1510}
1511
1512static int destroy_offload_callback_thread(struct stream_out *out)
1513{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001514 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001515 stop_compressed_output_l(out);
1516 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1517
1518 pthread_mutex_unlock(&out->lock);
1519 pthread_join(out->offload_thread, (void **) NULL);
1520 pthread_cond_destroy(&out->offload_cond);
1521
1522 return 0;
1523}
1524
Eric Laurent07eeafd2013-10-06 12:52:49 -07001525static bool allow_hdmi_channel_config(struct audio_device *adev)
1526{
1527 struct listnode *node;
1528 struct audio_usecase *usecase;
1529 bool ret = true;
1530
1531 list_for_each(node, &adev->usecase_list) {
1532 usecase = node_to_item(node, struct audio_usecase, list);
1533 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1534 /*
1535 * If voice call is already existing, do not proceed further to avoid
1536 * disabling/enabling both RX and TX devices, CSD calls, etc.
1537 * Once the voice call done, the HDMI channels can be configured to
1538 * max channels of remaining use cases.
1539 */
1540 if (usecase->id == USECASE_VOICE_CALL) {
1541 ALOGD("%s: voice call is active, no change in HDMI channels",
1542 __func__);
1543 ret = false;
1544 break;
1545 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1546 ALOGD("%s: multi channel playback is active, "
1547 "no change in HDMI channels", __func__);
1548 ret = false;
1549 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001550 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001551 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001552 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1553 ", no change in HDMI channels", __func__,
1554 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001555 ret = false;
1556 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557 }
1558 }
1559 }
1560 return ret;
1561}
1562
1563static int check_and_set_hdmi_channels(struct audio_device *adev,
1564 unsigned int channels)
1565{
1566 struct listnode *node;
1567 struct audio_usecase *usecase;
1568
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001569 unsigned int supported_channels = platform_edid_get_max_channels(
1570 adev->platform);
1571 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001572 /* Check if change in HDMI channel config is allowed */
1573 if (!allow_hdmi_channel_config(adev))
1574 return 0;
1575
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001576 if (channels > supported_channels)
1577 channels = supported_channels;
1578
Eric Laurent07eeafd2013-10-06 12:52:49 -07001579 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001580 ALOGD("%s: Requested channels are same as current channels(%d)",
1581 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001582 return 0;
1583 }
1584
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001585 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001586 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001587 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001588 adev->cur_hdmi_channels = channels;
1589
1590 /*
1591 * Deroute all the playback streams routed to HDMI so that
1592 * the back end is deactivated. Note that backend will not
1593 * be deactivated if any one stream is connected to it.
1594 */
1595 list_for_each(node, &adev->usecase_list) {
1596 usecase = node_to_item(node, struct audio_usecase, list);
1597 if (usecase->type == PCM_PLAYBACK &&
1598 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001599 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001600 }
1601 }
1602
1603 /*
1604 * Enable all the streams disabled above. Now the HDMI backend
1605 * will be activated with new channel configuration
1606 */
1607 list_for_each(node, &adev->usecase_list) {
1608 usecase = node_to_item(node, struct audio_usecase, list);
1609 if (usecase->type == PCM_PLAYBACK &&
1610 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001611 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001612 }
1613 }
1614
1615 return 0;
1616}
1617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618static int stop_output_stream(struct stream_out *out)
1619{
1620 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 struct audio_usecase *uc_info;
1622 struct audio_device *adev = out->dev;
1623
Eric Laurent994a6932013-07-17 11:51:42 -07001624 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 uc_info = get_usecase_from_list(adev, out->usecase);
1627 if (uc_info == NULL) {
1628 ALOGE("%s: Could not find the usecase (%d) in the list",
1629 __func__, out->usecase);
1630 return -EINVAL;
1631 }
1632
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001633 if (is_offload_usecase(out->usecase) &&
1634 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001635 if (adev->visualizer_stop_output != NULL)
1636 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001637
1638 audio_extn_dts_remove_state_notifier_node(out->usecase);
1639
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001640 if (adev->offload_effects_stop_output != NULL)
1641 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1642 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001643
Eric Laurent150dbfe2013-02-27 14:31:02 -08001644 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001645 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646
1647 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001648 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001650 list_remove(&uc_info->list);
1651 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001653 if (is_offload_usecase(out->usecase) &&
1654 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1655 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1656 ALOGV("Disable passthrough , reset mixer to pcm");
1657 /* NO_PASSTHROUGH */
1658 out->compr_config.codec->compr_passthr = 0;
1659 audio_extn_dolby_set_hdmi_config(adev, out);
1660 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1661 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001662 /* Must be called after removing the usecase from list */
1663 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1664 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1665
Eric Laurent994a6932013-07-17 11:51:42 -07001666 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 return ret;
1668}
1669
1670int start_output_stream(struct stream_out *out)
1671{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001673 int sink_channels = 0;
1674 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 struct audio_usecase *uc_info;
1676 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301677 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001679 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1680 ret = -EINVAL;
1681 goto error_config;
1682 }
1683
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301684 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1685 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1686 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301687
Naresh Tanniru80659832014-06-04 18:17:56 +05301688 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301689 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301690 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301691 goto error_config;
1692 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301693
Eric Laurentb23d5282013-05-14 15:27:20 -07001694 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 if (out->pcm_device_id < 0) {
1696 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1697 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001698 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001699 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 }
1701
1702 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001703
1704 if (!uc_info) {
1705 ret = -ENOMEM;
1706 goto error_config;
1707 }
1708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709 uc_info->id = out->usecase;
1710 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001711 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 uc_info->devices = out->devices;
1713 uc_info->in_snd_device = SND_DEVICE_NONE;
1714 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001715 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001716 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001717 if (is_offload_usecase(out->usecase)) {
1718 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001719 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1720 }
1721 }
Mingming Yin9c041392014-05-01 15:37:31 -07001722 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1723 if (!strncmp("true", prop_value, 4)) {
1724 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001725 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1726 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001727 check_and_set_hdmi_channels(adev, sink_channels);
1728 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001729 if (is_offload_usecase(out->usecase)) {
1730 unsigned int ch_count = out->compr_config.codec->ch_in;
1731 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1732 /* backend channel config for passthrough stream is stereo */
1733 ch_count = 2;
1734 check_and_set_hdmi_channels(adev, ch_count);
1735 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001736 check_and_set_hdmi_channels(adev, out->config.channels);
1737 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001738 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001739 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001740 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301742 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1743 adev->perf_lock_opts,
1744 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 select_devices(adev, out->usecase);
1746
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001747 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1748 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001749 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001750 unsigned int flags = PCM_OUT;
1751 unsigned int pcm_open_retry_count = 0;
1752 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1753 flags |= PCM_MMAP | PCM_NOIRQ;
1754 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1755 } else
1756 flags |= PCM_MONOTONIC;
1757
1758 while (1) {
1759 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1760 flags, &out->config);
1761 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1762 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1763 if (out->pcm != NULL) {
1764 pcm_close(out->pcm);
1765 out->pcm = NULL;
1766 }
1767 if (pcm_open_retry_count-- == 0) {
1768 ret = -EIO;
1769 goto error_open;
1770 }
1771 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1772 continue;
1773 }
1774 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001776
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001777 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1778 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001779
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001780 ALOGV("%s: pcm_prepare", __func__);
1781 if (pcm_is_ready(out->pcm)) {
1782 ret = pcm_prepare(out->pcm);
1783 if (ret < 0) {
1784 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1785 pcm_close(out->pcm);
1786 out->pcm = NULL;
1787 goto error_open;
1788 }
1789 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001790 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001791 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1792 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001794 out->compr = compress_open(adev->snd_card,
1795 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 COMPRESS_IN, &out->compr_config);
1797 if (out->compr && !is_compress_ready(out->compr)) {
1798 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1799 compress_close(out->compr);
1800 out->compr = NULL;
1801 ret = -EIO;
1802 goto error_open;
1803 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301804 /* compress_open sends params of the track, so reset the flag here */
1805 out->is_compr_metadata_avail = false;
1806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->offload_callback)
1808 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001809
Fred Oh3f43e742015-03-04 18:42:34 -08001810 /* Since small bufs uses blocking writes, a write will be blocked
1811 for the default max poll time (20s) in the event of an SSR.
1812 Reduce the poll time to observe and deal with SSR faster.
1813 */
1814 if (out->use_small_bufs) {
1815 compress_set_max_poll_wait(out->compr, 1000);
1816 }
1817
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001818 audio_extn_dts_create_state_notifier_node(out->usecase);
1819 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1820 popcount(out->channel_mask),
1821 out->playback_started);
1822
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001823#ifdef DS1_DOLBY_DDP_ENABLED
1824 if (audio_extn_is_dolby_format(out->format))
1825 audio_extn_dolby_send_ddp_endp_params(adev);
1826#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001827 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1828 if (adev->visualizer_start_output != NULL)
1829 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1830 if (adev->offload_effects_start_output != NULL)
1831 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001832 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301835 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001836 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301840 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001842error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301843 /*
1844 * sleep 50ms to allow sufficient time for kernel
1845 * drivers to recover incases like SSR.
1846 */
1847 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001848 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849}
1850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851static int check_input_parameters(uint32_t sample_rate,
1852 audio_format_t format,
1853 int channel_count)
1854{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001855 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001857 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001858 !voice_extn_compress_voip_is_format_supported(format) &&
1859 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001860
1861 switch (channel_count) {
1862 case 1:
1863 case 2:
1864 case 6:
1865 break;
1866 default:
1867 ret = -EINVAL;
1868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869
1870 switch (sample_rate) {
1871 case 8000:
1872 case 11025:
1873 case 12000:
1874 case 16000:
1875 case 22050:
1876 case 24000:
1877 case 32000:
1878 case 44100:
1879 case 48000:
1880 break;
1881 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001882 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 }
1884
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001885 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886}
1887
1888static size_t get_input_buffer_size(uint32_t sample_rate,
1889 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001890 int channel_count,
1891 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892{
1893 size_t size = 0;
1894
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001895 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1896 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001898 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001899 if (is_low_latency)
1900 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001901 /* ToDo: should use frame_size computed based on the format and
1902 channel_count here. */
1903 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001905 /* make sure the size is multiple of 32 bytes
1906 * At 48 kHz mono 16-bit PCM:
1907 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1908 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1909 */
1910 size += 0x1f;
1911 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001912
1913 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914}
1915
1916static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1917{
1918 struct stream_out *out = (struct stream_out *)stream;
1919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921}
1922
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001923static int out_set_sample_rate(struct audio_stream *stream __unused,
1924 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925{
1926 return -ENOSYS;
1927}
1928
1929static size_t out_get_buffer_size(const struct audio_stream *stream)
1930{
1931 struct stream_out *out = (struct stream_out *)stream;
1932
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001933 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001935 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1936 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001937
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001938 return out->config.period_size *
1939 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940}
1941
1942static uint32_t out_get_channels(const struct audio_stream *stream)
1943{
1944 struct stream_out *out = (struct stream_out *)stream;
1945
1946 return out->channel_mask;
1947}
1948
1949static audio_format_t out_get_format(const struct audio_stream *stream)
1950{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 struct stream_out *out = (struct stream_out *)stream;
1952
1953 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954}
1955
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001956static int out_set_format(struct audio_stream *stream __unused,
1957 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958{
1959 return -ENOSYS;
1960}
1961
1962static int out_standby(struct audio_stream *stream)
1963{
1964 struct stream_out *out = (struct stream_out *)stream;
1965 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301967 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1968 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001969 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1970 /* Ignore standby in case of voip call because the voip output
1971 * stream is closed in adev_close_output_stream()
1972 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301973 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001974 return 0;
1975 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001977 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001979 if (adev->adm_deregister_stream)
1980 adev->adm_deregister_stream(adev->adm_data, out->handle);
1981
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001982 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001984 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985 if (out->pcm) {
1986 pcm_close(out->pcm);
1987 out->pcm = NULL;
1988 }
1989 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001990 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301992 out->send_next_track_params = false;
1993 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001994 out->gapless_mdata.encoder_delay = 0;
1995 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996 if (out->compr != NULL) {
1997 compress_close(out->compr);
1998 out->compr = NULL;
1999 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002002 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 }
2004 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302005 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 return 0;
2007}
2008
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002009static int out_dump(const struct audio_stream *stream __unused,
2010 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011{
2012 return 0;
2013}
2014
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002015static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2016{
2017 int ret = 0;
2018 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002019
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002020 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002021 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002022 return -EINVAL;
2023 }
2024
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302025 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002026
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002027 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2028 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302029 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002030 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002031 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2032 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302033 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002034 }
2035
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002036 ALOGV("%s new encoder delay %u and padding %u", __func__,
2037 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2038
2039 return 0;
2040}
2041
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002042static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2043{
2044 return out == adev->primary_output || out == adev->voice_tx_output;
2045}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2048{
2049 struct stream_out *out = (struct stream_out *)stream;
2050 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002051 struct audio_usecase *usecase;
2052 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 struct str_parms *parms;
2054 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002055 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002056 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057
sangwoobc677242013-08-08 16:53:43 +09002058 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302061 if (!parms)
2062 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002063 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2064 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002066 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002067 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302070 * When HDMI cable is unplugged/usb hs is disconnected the
2071 * music playback is paused and the policy manager sends routing=0
2072 * But the audioflingercontinues to write data until standby time
2073 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002074 * Avoid this by routing audio to speaker until standby.
2075 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302076 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2077 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002079 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2080 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002081 }
2082
2083 /*
2084 * select_devices() call below switches all the usecases on the same
2085 * backend to the new device. Refer to check_usecases_codec_backend() in
2086 * the select_devices(). But how do we undo this?
2087 *
2088 * For example, music playback is active on headset (deep-buffer usecase)
2089 * and if we go to ringtones and select a ringtone, low-latency usecase
2090 * will be started on headset+speaker. As we can't enable headset+speaker
2091 * and headset devices at the same time, select_devices() switches the music
2092 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2093 * So when the ringtone playback is completed, how do we undo the same?
2094 *
2095 * We are relying on the out_set_parameters() call on deep-buffer output,
2096 * once the ringtone playback is ended.
2097 * NOTE: We should not check if the current devices are same as new devices.
2098 * Because select_devices() must be called to switch back the music
2099 * playback to headset.
2100 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002101 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002102 out->devices = val;
2103
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302104 if (!out->standby) {
2105 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2106 adev->perf_lock_opts,
2107 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302109 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2110 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002111
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002112 if (output_drives_call(adev, out)) {
2113 if(!voice_is_in_call(adev)) {
2114 if (adev->mode == AUDIO_MODE_IN_CALL) {
2115 adev->current_call_output = out;
2116 ret = voice_start_call(adev);
2117 }
2118 } else {
2119 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002120 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002121 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002122 }
2123 }
2124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002126 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002128
2129 if (out == adev->primary_output) {
2130 pthread_mutex_lock(&adev->lock);
2131 audio_extn_set_parameters(adev, parms);
2132 pthread_mutex_unlock(&adev->lock);
2133 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002134 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002135 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002136 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002137
2138 audio_extn_dts_create_state_notifier_node(out->usecase);
2139 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2140 popcount(out->channel_mask),
2141 out->playback_started);
2142
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002143 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002144 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302147error:
Eric Laurent994a6932013-07-17 11:51:42 -07002148 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 return ret;
2150}
2151
2152static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2153{
2154 struct stream_out *out = (struct stream_out *)stream;
2155 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002156 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 char value[256];
2158 struct str_parms *reply = str_parms_create();
2159 size_t i, j;
2160 int ret;
2161 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002162
2163 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002164 if (reply) {
2165 str_parms_destroy(reply);
2166 }
2167 if (query) {
2168 str_parms_destroy(query);
2169 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002170 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2171 return NULL;
2172 }
2173
Eric Laurent994a6932013-07-17 11:51:42 -07002174 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2176 if (ret >= 0) {
2177 value[0] = '\0';
2178 i = 0;
2179 while (out->supported_channel_masks[i] != 0) {
2180 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2181 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2182 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002183 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002185 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 first = false;
2187 break;
2188 }
2189 }
2190 i++;
2191 }
2192 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2193 str = str_parms_to_str(reply);
2194 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002195 voice_extn_out_get_parameters(out, query, reply);
2196 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002197 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002198 free(str);
2199 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002202
Alexy Joseph62142aa2015-11-16 15:10:34 -08002203
2204 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2205 if (ret >= 0) {
2206 value[0] = '\0';
2207 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2208 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302209 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002210 } else {
2211 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302212 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002213 }
2214 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002215 if (str)
2216 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002217 str = str_parms_to_str(reply);
2218 }
2219
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002220 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2221 if (ret >= 0) {
2222 value[0] = '\0';
2223 i = 0;
2224 first = true;
2225 while (out->supported_formats[i] != 0) {
2226 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2227 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2228 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002229 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002230 }
2231 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2232 first = false;
2233 break;
2234 }
2235 }
2236 i++;
2237 }
2238 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002239 if (str)
2240 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002241 str = str_parms_to_str(reply);
2242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 str_parms_destroy(query);
2244 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002245 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 return str;
2247}
2248
2249static uint32_t out_get_latency(const struct audio_stream_out *stream)
2250{
2251 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002252 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253
Alexy Josephaa54c872014-12-03 02:46:47 -08002254 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002255 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002256 } else {
2257 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002259 }
2260
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302261 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002262 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263}
2264
2265static int out_set_volume(struct audio_stream_out *stream, float left,
2266 float right)
2267{
Eric Laurenta9024de2013-04-04 09:19:12 -07002268 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 int volume[2];
2270
Eric Laurenta9024de2013-04-04 09:19:12 -07002271 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2272 /* only take left channel into account: the API is for stereo anyway */
2273 out->muted = (left == 0.0f);
2274 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002275 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002276 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2277 /*
2278 * Set mute or umute on HDMI passthrough stream.
2279 * Only take left channel into account.
2280 * Mute is 0 and unmute 1
2281 */
2282 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2283 } else {
2284 char mixer_ctl_name[128];
2285 struct audio_device *adev = out->dev;
2286 struct mixer_ctl *ctl;
2287 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002288 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002290 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2291 "Compress Playback %d Volume", pcm_device_id);
2292 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2293 if (!ctl) {
2294 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2295 __func__, mixer_ctl_name);
2296 return -EINVAL;
2297 }
2298 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2299 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2300 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2301 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002303 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 return -ENOSYS;
2306}
2307
2308static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2309 size_t bytes)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302313 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002314 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002316 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302317
Naresh Tanniru80659832014-06-04 18:17:56 +05302318 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002319
Ashish Jainbbce4322016-02-16 13:25:27 +05302320 if (is_offload_usecase(out->usecase)) {
2321 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302322 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2323 pthread_mutex_unlock(&out->lock);
2324 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302325 } else {
2326 /* increase written size during SSR to avoid mismatch
2327 * with the written frames count in AF
2328 */
2329 out->written += bytes / (out->config.channels * sizeof(short));
2330 ALOGD(" %s: sound card is not active/SSR state", __func__);
2331 ret= -EIO;
2332 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302333 }
2334 }
2335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002337 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002338 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002339 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2340 ret = voice_extn_compress_voip_start_output_stream(out);
2341 else
2342 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002343 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002346 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 goto exit;
2348 }
vivek mehta446c3962015-09-14 10:57:35 -07002349 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002350 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Ashish Jain81eb2a82015-05-13 10:52:34 +05302353 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002354 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302355 adev->is_channel_status_set = true;
2356 }
2357
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002358 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002359 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002360 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002361 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002362 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2363 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302364 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2365 ALOGD("copl(%p):send next track params in gapless", out);
2366 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2367 out->send_next_track_params = false;
2368 out->is_compr_metadata_avail = false;
2369 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370 }
2371
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302373 if (ret < 0)
2374 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002375 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002376 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302377 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002378 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302379 } else if (-ENETRESET == ret) {
2380 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2381 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2382 pthread_mutex_unlock(&out->lock);
2383 out_standby(&out->stream.common);
2384 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302386 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002388 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 out->playback_started = 1;
2390 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002391
2392 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2393 popcount(out->channel_mask),
2394 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 }
2396 pthread_mutex_unlock(&out->lock);
2397 return ret;
2398 } else {
2399 if (out->pcm) {
2400 if (out->muted)
2401 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002402
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002404
2405 if (adev->adm_request_focus)
2406 adev->adm_request_focus(adev->adm_data, out->handle);
2407
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002408 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2409 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2410 else
2411 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002412
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302413 if (ret < 0)
2414 ret = -errno;
2415 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002416 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002417
2418 if (adev->adm_abandon_focus)
2419 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 }
2422
2423exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302424 /* ToDo: There may be a corner case when SSR happens back to back during
2425 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302426 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302427 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302428 }
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 pthread_mutex_unlock(&out->lock);
2431
2432 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002433 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002434 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302435 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302436 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302437 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302438 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302439 out->standby = true;
2440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302442 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302443 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 }
2445 return bytes;
2446}
2447
2448static int out_get_render_position(const struct audio_stream_out *stream,
2449 uint32_t *dsp_frames)
2450{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302452 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002453
2454 if (dsp_frames == NULL)
2455 return -EINVAL;
2456
2457 *dsp_frames = 0;
2458 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002459 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302462 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302464 if (ret < 0)
2465 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 ALOGVV("%s rendered frames %d sample_rate %d",
2467 __func__, *dsp_frames, out->sample_rate);
2468 }
2469 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302470 if (-ENETRESET == ret) {
2471 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2472 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2473 return -EINVAL;
2474 } else if(ret < 0) {
2475 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2476 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302477 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2478 /*
2479 * Handle corner case where compress session is closed during SSR
2480 * and timestamp is queried
2481 */
2482 ALOGE(" ERROR: sound card not active, return error");
2483 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302484 } else {
2485 return 0;
2486 }
Zhou Song32a556e2015-05-05 10:46:56 +08002487 } else if (audio_is_linear_pcm(out->format)) {
2488 *dsp_frames = out->written;
2489 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 } else
2491 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492}
2493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002494static int out_add_audio_effect(const struct audio_stream *stream __unused,
2495 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496{
2497 return 0;
2498}
2499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002500static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2501 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
2503 return 0;
2504}
2505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002506static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2507 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508{
2509 return -EINVAL;
2510}
2511
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002512static int out_get_presentation_position(const struct audio_stream_out *stream,
2513 uint64_t *frames, struct timespec *timestamp)
2514{
2515 struct stream_out *out = (struct stream_out *)stream;
2516 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002517 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002518
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002519 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002520
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002521 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002522 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302523 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002524 &out->sample_rate);
2525 ALOGVV("%s rendered frames %ld sample_rate %d",
2526 __func__, dsp_frames, out->sample_rate);
2527 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302528 if (ret < 0)
2529 ret = -errno;
2530 if (-ENETRESET == ret) {
2531 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2532 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2533 ret = -EINVAL;
2534 } else
2535 ret = 0;
2536
Eric Laurent949a0892013-09-20 09:20:13 -07002537 /* this is the best we can do */
2538 clock_gettime(CLOCK_MONOTONIC, timestamp);
2539 }
2540 } else {
2541 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002542 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002543 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2544 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002545 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002546 // This adjustment accounts for buffering after app processor.
2547 // It is based on estimated DSP latency per use case, rather than exact.
2548 signed_frames -=
2549 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2550
Eric Laurent949a0892013-09-20 09:20:13 -07002551 // It would be unusual for this value to be negative, but check just in case ...
2552 if (signed_frames >= 0) {
2553 *frames = signed_frames;
2554 ret = 0;
2555 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002556 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302557 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2558 *frames = out->written;
2559 clock_gettime(CLOCK_MONOTONIC, timestamp);
2560 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002561 }
2562 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002563 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002564 return ret;
2565}
2566
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567static int out_set_callback(struct audio_stream_out *stream,
2568 stream_callback_t callback, void *cookie)
2569{
2570 struct stream_out *out = (struct stream_out *)stream;
2571
2572 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002573 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 out->offload_callback = callback;
2575 out->offload_cookie = cookie;
2576 pthread_mutex_unlock(&out->lock);
2577 return 0;
2578}
2579
2580static int out_pause(struct audio_stream_out* stream)
2581{
2582 struct stream_out *out = (struct stream_out *)stream;
2583 int status = -ENOSYS;
2584 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002585 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002586 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002587 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302589 struct audio_device *adev = out->dev;
2590 int snd_scard_state = get_snd_card_state(adev);
2591
2592 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2593 status = compress_pause(out->compr);
2594
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002596
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302597 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002598 audio_extn_dts_notify_playback_state(out->usecase, 0,
2599 out->sample_rate, popcount(out->channel_mask),
2600 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002601 }
2602 pthread_mutex_unlock(&out->lock);
2603 }
2604 return status;
2605}
2606
2607static int out_resume(struct audio_stream_out* stream)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610 int status = -ENOSYS;
2611 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002612 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002613 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002615 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302617 struct audio_device *adev = out->dev;
2618 int snd_scard_state = get_snd_card_state(adev);
2619
2620 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2621 status = compress_resume(out->compr);
2622
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002624
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302625 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002626 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2627 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002628 }
2629 pthread_mutex_unlock(&out->lock);
2630 }
2631 return status;
2632}
2633
2634static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2635{
2636 struct stream_out *out = (struct stream_out *)stream;
2637 int status = -ENOSYS;
2638 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002639 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002640 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002641 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2642 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2643 else
2644 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2645 pthread_mutex_unlock(&out->lock);
2646 }
2647 return status;
2648}
2649
2650static int out_flush(struct audio_stream_out* stream)
2651{
2652 struct stream_out *out = (struct stream_out *)stream;
2653 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002654 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002655 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002656 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657 stop_compressed_output_l(out);
2658 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002659 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 return 0;
2661 }
2662 return -ENOSYS;
2663}
2664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665/** audio_stream_in implementation **/
2666static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2667{
2668 struct stream_in *in = (struct stream_in *)stream;
2669
2670 return in->config.rate;
2671}
2672
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002673static int in_set_sample_rate(struct audio_stream *stream __unused,
2674 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
2676 return -ENOSYS;
2677}
2678
2679static size_t in_get_buffer_size(const struct audio_stream *stream)
2680{
2681 struct stream_in *in = (struct stream_in *)stream;
2682
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002683 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2684 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002685 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2686 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002687
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002688 return in->config.period_size *
2689 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690}
2691
2692static uint32_t in_get_channels(const struct audio_stream *stream)
2693{
2694 struct stream_in *in = (struct stream_in *)stream;
2695
2696 return in->channel_mask;
2697}
2698
2699static audio_format_t in_get_format(const struct audio_stream *stream)
2700{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002701 struct stream_in *in = (struct stream_in *)stream;
2702
2703 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002706static int in_set_format(struct audio_stream *stream __unused,
2707 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
2709 return -ENOSYS;
2710}
2711
2712static int in_standby(struct audio_stream *stream)
2713{
2714 struct stream_in *in = (struct stream_in *)stream;
2715 struct audio_device *adev = in->dev;
2716 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302717 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2718 stream, in->usecase, use_case_table[in->usecase]);
2719
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002720 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2721 /* Ignore standby in case of voip call because the voip input
2722 * stream is closed in adev_close_input_stream()
2723 */
2724 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2725 return status;
2726 }
2727
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002728 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002729 if (!in->standby && in->is_st_session) {
2730 ALOGD("%s: sound trigger pcm stop lab", __func__);
2731 audio_extn_sound_trigger_stop_lab(in);
2732 in->standby = 1;
2733 }
2734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002736 if (adev->adm_deregister_stream)
2737 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2738
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002739 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002741 if (in->pcm) {
2742 pcm_close(in->pcm);
2743 in->pcm = NULL;
2744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002746 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 }
2748 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 return status;
2751}
2752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002753static int in_dump(const struct audio_stream *stream __unused,
2754 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 return 0;
2757}
2758
2759static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2760{
2761 struct stream_in *in = (struct stream_in *)stream;
2762 struct audio_device *adev = in->dev;
2763 struct str_parms *parms;
2764 char *str;
2765 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002766 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302768 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 parms = str_parms_create_str(kvpairs);
2770
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302771 if (!parms)
2772 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002773 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002774 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002775
2776 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2777 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 val = atoi(value);
2779 /* no audio source uses val == 0 */
2780 if ((in->source != val) && (val != 0)) {
2781 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002782 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2783 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2784 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002785 (in->config.rate == 8000 || in->config.rate == 16000 ||
2786 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002787 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002788 err = voice_extn_compress_voip_open_input_stream(in);
2789 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002790 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002791 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002792 }
2793 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 }
2795 }
2796
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002797 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2798 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002800 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 in->device = val;
2802 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002803 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002804 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 }
2806 }
2807
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002808done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002810 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811
2812 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302813error:
Eric Laurent994a6932013-07-17 11:51:42 -07002814 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 return ret;
2816}
2817
2818static char* in_get_parameters(const struct audio_stream *stream,
2819 const char *keys)
2820{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002821 struct stream_in *in = (struct stream_in *)stream;
2822 struct str_parms *query = str_parms_create_str(keys);
2823 char *str;
2824 char value[256];
2825 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002826
2827 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002828 if (reply) {
2829 str_parms_destroy(reply);
2830 }
2831 if (query) {
2832 str_parms_destroy(query);
2833 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002834 ALOGE("in_get_parameters: failed to create query or reply");
2835 return NULL;
2836 }
2837
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002838 ALOGV("%s: enter: keys - %s", __func__, keys);
2839
2840 voice_extn_in_get_parameters(in, query, reply);
2841
2842 str = str_parms_to_str(reply);
2843 str_parms_destroy(query);
2844 str_parms_destroy(reply);
2845
2846 ALOGV("%s: exit: returns - %s", __func__, str);
2847 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848}
2849
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002850static int in_set_gain(struct audio_stream_in *stream __unused,
2851 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852{
2853 return 0;
2854}
2855
2856static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2857 size_t bytes)
2858{
2859 struct stream_in *in = (struct stream_in *)stream;
2860 struct audio_device *adev = in->dev;
2861 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302862 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002864 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302865
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002866 if (in->is_st_session) {
2867 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2868 /* Read from sound trigger HAL */
2869 audio_extn_sound_trigger_read(in, buffer, bytes);
2870 pthread_mutex_unlock(&in->lock);
2871 return bytes;
2872 }
2873
Ashish Jainbbce4322016-02-16 13:25:27 +05302874 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002875 ALOGD(" %s: sound card is not active/SSR state", __func__);
2876 ret= -EIO;;
2877 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302878 }
2879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002881 pthread_mutex_lock(&adev->lock);
2882 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2883 ret = voice_extn_compress_voip_start_input_stream(in);
2884 else
2885 ret = start_input_stream(in);
2886 pthread_mutex_unlock(&adev->lock);
2887 if (ret != 0) {
2888 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 }
2890 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002891 if (adev->adm_register_input_stream)
2892 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002895 if (adev->adm_request_focus)
2896 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002899 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002900 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002901 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2902 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002903 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2904 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002905 else
2906 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302907 if (ret < 0)
2908 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 }
2910
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002911 if (adev->adm_abandon_focus)
2912 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 /*
2915 * Instead of writing zeroes here, we could trust the hardware
2916 * to always provide zeroes when muted.
2917 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302918 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2919 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 memset(buffer, 0, bytes);
2921
2922exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302923 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302924 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002925 if (-ENETRESET == ret)
2926 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 pthread_mutex_unlock(&in->lock);
2929
2930 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302931 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302932 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302933 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302934 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302935 in->standby = true;
2936 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302937 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002939 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05302940 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302941 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 }
2943 return bytes;
2944}
2945
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002946static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947{
2948 return 0;
2949}
2950
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002951static int add_remove_audio_effect(const struct audio_stream *stream,
2952 effect_handle_t effect,
2953 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002955 struct stream_in *in = (struct stream_in *)stream;
2956 int status = 0;
2957 effect_descriptor_t desc;
2958
2959 status = (*effect)->get_descriptor(effect, &desc);
2960 if (status != 0)
2961 return status;
2962
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002963 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002964 pthread_mutex_lock(&in->dev->lock);
2965 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2966 in->enable_aec != enable &&
2967 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2968 in->enable_aec = enable;
2969 if (!in->standby)
2970 select_devices(in->dev, in->usecase);
2971 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002972 if (in->enable_ns != enable &&
2973 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2974 in->enable_ns = enable;
2975 if (!in->standby)
2976 select_devices(in->dev, in->usecase);
2977 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002978 pthread_mutex_unlock(&in->dev->lock);
2979 pthread_mutex_unlock(&in->lock);
2980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 return 0;
2982}
2983
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002984static int in_add_audio_effect(const struct audio_stream *stream,
2985 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986{
Eric Laurent994a6932013-07-17 11:51:42 -07002987 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002988 return add_remove_audio_effect(stream, effect, true);
2989}
2990
2991static int in_remove_audio_effect(const struct audio_stream *stream,
2992 effect_handle_t effect)
2993{
Eric Laurent994a6932013-07-17 11:51:42 -07002994 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002995 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996}
2997
2998static int adev_open_output_stream(struct audio_hw_device *dev,
2999 audio_io_handle_t handle,
3000 audio_devices_t devices,
3001 audio_output_flags_t flags,
3002 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003003 struct audio_stream_out **stream_out,
3004 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005{
3006 struct audio_device *adev = (struct audio_device *)dev;
3007 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003008 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003009 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303012
3013 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3014 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003015 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303016 return -EINVAL;
3017 }
3018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3020
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303021 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3022 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3023 devices, flags, &out->stream);
3024
3025
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003026 if (!out) {
3027 return -ENOMEM;
3028 }
3029
Haynes Mathew George204045b2015-02-25 20:32:03 -08003030 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003031 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003032 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 if (devices == AUDIO_DEVICE_NONE)
3035 devices = AUDIO_DEVICE_OUT_SPEAKER;
3036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 out->flags = flags;
3038 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003039 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003040 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003041 out->sample_rate = config->sample_rate;
3042 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3043 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003044 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003045 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003046 out->non_blocking = 0;
3047 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048
3049 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003050 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303051 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3052 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003053 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3054 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3055
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003056 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003057 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3058 ret = read_hdmi_channel_masks(out);
3059
3060 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3061 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003062 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003063 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003064 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003065
3066 if (config->sample_rate == 0)
3067 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3068 if (config->channel_mask == 0)
3069 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3070
3071 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3074 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003076 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3079 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003080 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003081 ret = voice_extn_compress_voip_open_output_stream(out);
3082 if (ret != 0) {
3083 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3084 __func__, ret);
3085 goto error_open;
3086 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003087 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3088 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3089
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3091 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3092 ALOGE("%s: Unsupported Offload information", __func__);
3093 ret = -EINVAL;
3094 goto error_open;
3095 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003096
3097 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3098 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3099 ALOGV("read and update_pass through formats");
3100 ret = audio_extn_dolby_update_passt_formats(adev, out);
3101 if(ret != 0) {
3102 goto error_open;
3103 }
3104 if(config->offload_info.format == 0)
3105 config->offload_info.format = out->supported_formats[0];
3106 }
3107
Mingming Yin90310102013-11-13 16:57:00 -08003108 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003109 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003110 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 ret = -EINVAL;
3112 goto error_open;
3113 }
3114
3115 out->compr_config.codec = (struct snd_codec *)
3116 calloc(1, sizeof(struct snd_codec));
3117
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003118 if (!out->compr_config.codec) {
3119 ret = -ENOMEM;
3120 goto error_open;
3121 }
3122
vivek mehta0ea887a2015-08-26 14:01:20 -07003123 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003124 out->usecase = get_offload_usecase(adev, true);
3125 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003126 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003127 out->stream.set_callback = out_set_callback;
3128 out->stream.pause = out_pause;
3129 out->stream.resume = out_resume;
3130 out->stream.drain = out_drain;
3131 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003132 out->usecase = get_offload_usecase(adev, false);
3133 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003134 }
vivek mehta446c3962015-09-14 10:57:35 -07003135
3136 if (out->usecase == USECASE_INVALID) {
Alexy Josephb1379942016-01-29 15:49:38 -08003137 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
vivek mehta446c3962015-09-14 10:57:35 -07003138 ret = -EEXIST;
3139 goto error_open;
3140 }
3141
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 if (config->offload_info.channel_mask)
3143 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003144 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003146 config->offload_info.channel_mask = config->channel_mask;
3147 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003148 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149 out->sample_rate = config->offload_info.sample_rate;
3150
Mingming Yin3ee55c62014-08-04 14:23:35 -07003151 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003153 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003154 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003155 audio_extn_dolby_get_snd_codec_id(adev, out,
3156 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003157 else
3158 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003160
3161 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3162 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003163 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003164 platform_get_pcm_offload_buffer_size(&config->offload_info);
3165 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3166 out->compr_config.fragment_size =
3167 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003168 } else {
3169 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003170 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003171 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3173 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003174 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003175 out->compr_config.codec->bit_rate =
3176 config->offload_info.bit_rate;
3177 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003179 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303180 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003181 /*TODO: Do we need to change it for passthrough */
3182 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003183
Manish Dewangana6fc5442015-08-24 20:30:31 +05303184 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3185 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3186 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3187 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003188 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3189 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003190 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003191 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003192 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3193 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003194
Mingming Yin3ee55c62014-08-04 14:23:35 -07003195 if (out->bit_width == 24) {
3196 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3197 }
3198
Amit Shekhar6f461b12014-08-01 14:52:58 -07003199 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303200 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003201
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003202 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3203 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003204
Mingming Yin497419f2015-07-01 16:57:32 -07003205 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003206 //this flag is set from framework only if its for PCM formats
3207 //no need to check for PCM format again
3208 out->non_blocking = 0;
3209 out->use_small_bufs = true;
3210 ALOGI("Keep write blocking for small buff: non_blockling %d",
3211 out->non_blocking);
3212 }
3213
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003214 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303215 out->send_next_track_params = false;
3216 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003217 out->offload_state = OFFLOAD_STATE_IDLE;
3218 out->playback_started = 0;
3219
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003220 audio_extn_dts_create_state_notifier_node(out->usecase);
3221
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003222 create_offload_callback_thread(out);
3223 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3224 __func__, config->offload_info.version,
3225 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003226 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003227 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003228 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3229 ret = voice_check_and_set_incall_music_usecase(adev, out);
3230 if (ret != 0) {
3231 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3232 __func__, ret);
3233 goto error_open;
3234 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003235 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3236 if (config->sample_rate == 0)
3237 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3238 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3239 config->sample_rate != 8000) {
3240 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3241 ret = -EINVAL;
3242 goto error_open;
3243 }
3244 out->sample_rate = config->sample_rate;
3245 out->config.rate = config->sample_rate;
3246 if (config->format == AUDIO_FORMAT_DEFAULT)
3247 config->format = AUDIO_FORMAT_PCM_16_BIT;
3248 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3249 config->format = AUDIO_FORMAT_PCM_16_BIT;
3250 ret = -EINVAL;
3251 goto error_open;
3252 }
3253 out->format = config->format;
3254 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3255 out->config = pcm_config_afe_proxy_playback;
3256 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003257 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3258 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3259 out->config = pcm_config_low_latency;
3260 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003261 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003262 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3264 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003265 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003266 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3267 format = AUDIO_FORMAT_PCM_16_BIT;
3268 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3269 out->config = pcm_config_deep_buffer;
3270 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003271 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003272 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003273 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003274 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003275 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003276 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 }
3278
Amit Shekhar1d896042014-10-03 13:16:09 -07003279 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3280 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003281 /* TODO remove this hardcoding and check why width is zero*/
3282 if (out->bit_width == 0)
3283 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003284 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3285 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003286 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303287 out->bit_width, out->channel_mask,
3288 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003289 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3290 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3291 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003292 if(adev->primary_output == NULL)
3293 adev->primary_output = out;
3294 else {
3295 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003296 ret = -EEXIST;
3297 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003298 }
3299 }
3300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301 /* Check if this usecase is already existing */
3302 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003303 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3304 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003307 ret = -EEXIST;
3308 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 }
3310 pthread_mutex_unlock(&adev->lock);
3311
3312 out->stream.common.get_sample_rate = out_get_sample_rate;
3313 out->stream.common.set_sample_rate = out_set_sample_rate;
3314 out->stream.common.get_buffer_size = out_get_buffer_size;
3315 out->stream.common.get_channels = out_get_channels;
3316 out->stream.common.get_format = out_get_format;
3317 out->stream.common.set_format = out_set_format;
3318 out->stream.common.standby = out_standby;
3319 out->stream.common.dump = out_dump;
3320 out->stream.common.set_parameters = out_set_parameters;
3321 out->stream.common.get_parameters = out_get_parameters;
3322 out->stream.common.add_audio_effect = out_add_audio_effect;
3323 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3324 out->stream.get_latency = out_get_latency;
3325 out->stream.set_volume = out_set_volume;
3326 out->stream.write = out_write;
3327 out->stream.get_render_position = out_get_render_position;
3328 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003329 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003332 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003333 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334
3335 config->format = out->stream.common.get_format(&out->stream.common);
3336 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3337 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3338
3339 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303340 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003341 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003342
3343 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3344 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3345 popcount(out->channel_mask), out->playback_started);
3346
Eric Laurent994a6932013-07-17 11:51:42 -07003347 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003349
3350error_open:
3351 free(out);
3352 *stream_out = NULL;
3353 ALOGD("%s: exit: ret %d", __func__, ret);
3354 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355}
3356
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003357static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 struct audio_stream_out *stream)
3359{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 struct stream_out *out = (struct stream_out *)stream;
3361 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003362 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003363
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303364 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3365
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003366 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303367 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003368 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303369 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003370 if(ret != 0)
3371 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3372 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003373 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003374 out_standby(&stream->common);
3375
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003376 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003377 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003379 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 if (out->compr_config.codec != NULL)
3381 free(out->compr_config.codec);
3382 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003383
3384 if (adev->voice_tx_output == out)
3385 adev->voice_tx_output = NULL;
3386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387 pthread_cond_destroy(&out->cond);
3388 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003390 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391}
3392
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003393static void close_compress_sessions(struct audio_device *adev)
3394{
Mingming Yin7b762e72015-03-04 13:47:32 -08003395 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303396 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003397 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003398 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303399
3400 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003401 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303402 if (is_offload_usecase(usecase->id)) {
3403 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003404 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3405 out = usecase->stream.out;
3406 pthread_mutex_unlock(&adev->lock);
3407 out_standby(&out->stream.common);
3408 pthread_mutex_lock(&adev->lock);
3409 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303410 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003411 }
3412 pthread_mutex_unlock(&adev->lock);
3413}
3414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3416{
3417 struct audio_device *adev = (struct audio_device *)dev;
3418 struct str_parms *parms;
3419 char *str;
3420 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003421 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003422 int ret;
3423 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003425 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303428 if (!parms)
3429 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003430 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3431 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303432 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303433 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303434 struct listnode *node;
3435 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303436 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303437 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003438 //close compress sessions on OFFLINE status
3439 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303440 } else if (strstr(snd_card_status, "ONLINE")) {
3441 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303442 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003443 //send dts hpx license if enabled
3444 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303445 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303446 }
3447
3448 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003449 status = voice_set_parameters(adev, parms);
3450 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003451 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003453 status = platform_set_parameters(adev->platform, parms);
3454 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003455 goto done;
3456
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003457 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3458 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003459 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3461 adev->bluetooth_nrec = true;
3462 else
3463 adev->bluetooth_nrec = false;
3464 }
3465
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003466 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3467 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3469 adev->screen_off = false;
3470 else
3471 adev->screen_off = true;
3472 }
3473
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003474 ret = str_parms_get_int(parms, "rotation", &val);
3475 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003476 bool reverse_speakers = false;
3477 switch(val) {
3478 // FIXME: note that the code below assumes that the speakers are in the correct placement
3479 // relative to the user when the device is rotated 90deg from its default rotation. This
3480 // assumption is device-specific, not platform-specific like this code.
3481 case 270:
3482 reverse_speakers = true;
3483 break;
3484 case 0:
3485 case 90:
3486 case 180:
3487 break;
3488 default:
3489 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003490 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003491 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003492 if (status == 0) {
3493 if (adev->speaker_lr_swap != reverse_speakers) {
3494 adev->speaker_lr_swap = reverse_speakers;
3495 // only update the selected device if there is active pcm playback
3496 struct audio_usecase *usecase;
3497 struct listnode *node;
3498 list_for_each(node, &adev->usecase_list) {
3499 usecase = node_to_item(node, struct audio_usecase, list);
3500 if (usecase->type == PCM_PLAYBACK) {
3501 select_devices(adev, usecase->id);
3502 break;
3503 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003504 }
3505 }
3506 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003507 }
3508
Mingming Yin514a8bc2014-07-29 15:22:21 -07003509 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3510 if (ret >= 0) {
3511 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3512 adev->bt_wb_speech_enabled = true;
3513 else
3514 adev->bt_wb_speech_enabled = false;
3515 }
3516
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3518 if (ret >= 0) {
3519 val = atoi(value);
3520 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3521 ALOGV("cache new edid");
3522 platform_cache_edid(adev->platform);
3523 }
3524 }
3525
3526 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3527 if (ret >= 0) {
3528 val = atoi(value);
3529 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3530 ALOGV("invalidate cached edid");
3531 platform_invalidate_edid(adev->platform);
3532 }
3533 }
3534
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003535 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003536
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003537done:
3538 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003539 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303540error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003541 ALOGV("%s: exit with code(%d)", __func__, status);
3542 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543}
3544
3545static char* adev_get_parameters(const struct audio_hw_device *dev,
3546 const char *keys)
3547{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003548 struct audio_device *adev = (struct audio_device *)dev;
3549 struct str_parms *reply = str_parms_create();
3550 struct str_parms *query = str_parms_create_str(keys);
3551 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303552 char value[256] = {0};
3553 int ret = 0;
3554
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003555 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003556 if (reply) {
3557 str_parms_destroy(reply);
3558 }
3559 if (query) {
3560 str_parms_destroy(query);
3561 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003562 ALOGE("adev_get_parameters: failed to create query or reply");
3563 return NULL;
3564 }
3565
Naresh Tannirud7205b62014-06-20 02:54:48 +05303566 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3567 sizeof(value));
3568 if (ret >=0) {
3569 int val = 1;
3570 pthread_mutex_lock(&adev->snd_card_status.lock);
3571 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3572 val = 0;
3573 pthread_mutex_unlock(&adev->snd_card_status.lock);
3574 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3575 goto exit;
3576 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003577
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003578 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003579 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003580 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003581 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303582 pthread_mutex_unlock(&adev->lock);
3583
Naresh Tannirud7205b62014-06-20 02:54:48 +05303584exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003585 str = str_parms_to_str(reply);
3586 str_parms_destroy(query);
3587 str_parms_destroy(reply);
3588
3589 ALOGV("%s: exit: returns - %s", __func__, str);
3590 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591}
3592
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003593static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594{
3595 return 0;
3596}
3597
3598static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3599{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003600 int ret;
3601 struct audio_device *adev = (struct audio_device *)dev;
3602 pthread_mutex_lock(&adev->lock);
3603 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003604 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003605 pthread_mutex_unlock(&adev->lock);
3606 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607}
3608
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003609static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3610 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611{
3612 return -ENOSYS;
3613}
3614
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003615static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3616 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617{
3618 return -ENOSYS;
3619}
3620
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003621static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3622 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623{
3624 return -ENOSYS;
3625}
3626
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003627static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3628 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629{
3630 return -ENOSYS;
3631}
3632
3633static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3634{
3635 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 pthread_mutex_lock(&adev->lock);
3638 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003639 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003641 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003642 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003643 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003644 adev->current_call_output = NULL;
3645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 }
3647 pthread_mutex_unlock(&adev->lock);
3648 return 0;
3649}
3650
3651static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3652{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003653 int ret;
3654
3655 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003656 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003657 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3658 pthread_mutex_unlock(&adev->lock);
3659
3660 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661}
3662
3663static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3664{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003665 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 return 0;
3667}
3668
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003669static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 const struct audio_config *config)
3671{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003672 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003674 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3675 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676}
3677
3678static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003679 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 audio_devices_t devices,
3681 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003682 struct audio_stream_in **stream_in,
3683 audio_input_flags_t flags __unused,
3684 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003685 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686{
3687 struct audio_device *adev = (struct audio_device *)dev;
3688 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003689 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003690 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003691 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 *stream_in = NULL;
3694 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3695 return -EINVAL;
3696
3697 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003698
3699 if (!in) {
3700 ALOGE("failed to allocate input stream");
3701 return -ENOMEM;
3702 }
3703
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303704 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003705 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3706 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003708 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003709 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 in->stream.common.get_sample_rate = in_get_sample_rate;
3712 in->stream.common.set_sample_rate = in_set_sample_rate;
3713 in->stream.common.get_buffer_size = in_get_buffer_size;
3714 in->stream.common.get_channels = in_get_channels;
3715 in->stream.common.get_format = in_get_format;
3716 in->stream.common.set_format = in_set_format;
3717 in->stream.common.standby = in_standby;
3718 in->stream.common.dump = in_dump;
3719 in->stream.common.set_parameters = in_set_parameters;
3720 in->stream.common.get_parameters = in_get_parameters;
3721 in->stream.common.add_audio_effect = in_add_audio_effect;
3722 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3723 in->stream.set_gain = in_set_gain;
3724 in->stream.read = in_read;
3725 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3726
3727 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003728 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 in->standby = 1;
3731 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003732 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003733 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734
3735 /* Update config params with the requested sample rate and channels */
3736 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003737 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3738 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3739 is_low_latency = true;
3740#if LOW_LATENCY_CAPTURE_USE_CASE
3741 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3742#endif
3743 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003746 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003748 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303749 if (adev->mode != AUDIO_MODE_IN_CALL) {
3750 ret = -EINVAL;
3751 goto err_open;
3752 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003753 if (config->sample_rate == 0)
3754 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3755 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3756 config->sample_rate != 8000) {
3757 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3758 ret = -EINVAL;
3759 goto err_open;
3760 }
3761 if (config->format == AUDIO_FORMAT_DEFAULT)
3762 config->format = AUDIO_FORMAT_PCM_16_BIT;
3763 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3764 config->format = AUDIO_FORMAT_PCM_16_BIT;
3765 ret = -EINVAL;
3766 goto err_open;
3767 }
3768
3769 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3770 in->config = pcm_config_afe_proxy_record;
3771 in->config.channels = channel_count;
3772 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303773 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3774 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003775 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003776 audio_extn_compr_cap_format_supported(config->format) &&
3777 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003778 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003779 } else {
3780 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003781 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003782 buffer_size = get_input_buffer_size(config->sample_rate,
3783 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003784 channel_count,
3785 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003786 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003787 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3788 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3789 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003790 (in->config.rate == 8000 || in->config.rate == 16000 ||
3791 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003792 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3793 voice_extn_compress_voip_open_input_stream(in);
3794 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003797 /* This stream could be for sound trigger lab,
3798 get sound trigger pcm if present */
3799 audio_extn_sound_trigger_check_and_get_session(in);
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003802 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003803 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
3805err_open:
3806 free(in);
3807 *stream_in = NULL;
3808 return ret;
3809}
3810
3811static void adev_close_input_stream(struct audio_hw_device *dev,
3812 struct audio_stream_in *stream)
3813{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003814 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003815 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003816 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303817
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303818 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003819
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303820 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003821 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303822
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003823 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303824 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003825 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303826 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003827 if (ret != 0)
3828 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3829 __func__, ret);
3830 } else
3831 in_standby(&stream->common);
3832
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003833 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003834 audio_extn_ssr_deinit();
3835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836
Mingming Yine62d7842013-10-25 16:26:03 -07003837 if(audio_extn_compr_cap_enabled() &&
3838 audio_extn_compr_cap_format_supported(in->config.format))
3839 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003840
Mingming Yinfd7607b2016-01-22 12:48:44 -08003841 if (in->is_st_session) {
3842 ALOGV("%s: sound trigger pcm stop lab", __func__);
3843 audio_extn_sound_trigger_stop_lab(in);
3844 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003845 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 return;
3847}
3848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003849static int adev_dump(const audio_hw_device_t *device __unused,
3850 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851{
3852 return 0;
3853}
3854
3855static int adev_close(hw_device_t *device)
3856{
3857 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003858
3859 if (!adev)
3860 return 0;
3861
3862 pthread_mutex_lock(&adev_init_lock);
3863
3864 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003865 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003866 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003867 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003868 audio_route_free(adev->audio_route);
3869 free(adev->snd_dev_ref_cnt);
3870 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003871 if (adev->adm_deinit)
3872 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003873 free(device);
3874 adev = NULL;
3875 }
3876 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 return 0;
3879}
3880
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003881/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3882 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3883 * just that it _might_ work.
3884 */
3885static int period_size_is_plausible_for_low_latency(int period_size)
3886{
3887 switch (period_size) {
3888 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003889 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003890 case 240:
3891 case 320:
3892 case 480:
3893 return 1;
3894 default:
3895 return 0;
3896 }
3897}
3898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899static int adev_open(const hw_module_t *module, const char *name,
3900 hw_device_t **device)
3901{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003902 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003904 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3906
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003907 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003908 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003909 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003910 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003911 ALOGD("%s: returning existing instance of adev", __func__);
3912 ALOGD("%s: exit", __func__);
3913 pthread_mutex_unlock(&adev_init_lock);
3914 return 0;
3915 }
3916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 adev = calloc(1, sizeof(struct audio_device));
3918
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003919 if (!adev) {
3920 pthread_mutex_unlock(&adev_init_lock);
3921 return -ENOMEM;
3922 }
3923
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003924 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3927 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3928 adev->device.common.module = (struct hw_module_t *)module;
3929 adev->device.common.close = adev_close;
3930
3931 adev->device.init_check = adev_init_check;
3932 adev->device.set_voice_volume = adev_set_voice_volume;
3933 adev->device.set_master_volume = adev_set_master_volume;
3934 adev->device.get_master_volume = adev_get_master_volume;
3935 adev->device.set_master_mute = adev_set_master_mute;
3936 adev->device.get_master_mute = adev_get_master_mute;
3937 adev->device.set_mode = adev_set_mode;
3938 adev->device.set_mic_mute = adev_set_mic_mute;
3939 adev->device.get_mic_mute = adev_get_mic_mute;
3940 adev->device.set_parameters = adev_set_parameters;
3941 adev->device.get_parameters = adev_get_parameters;
3942 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3943 adev->device.open_output_stream = adev_open_output_stream;
3944 adev->device.close_output_stream = adev_close_output_stream;
3945 adev->device.open_input_stream = adev_open_input_stream;
3946 adev->device.close_input_stream = adev_close_input_stream;
3947 adev->device.dump = adev_dump;
3948
3949 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003951 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003952 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003955 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003956 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003957 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003958 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003959 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003960 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003961 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303962 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303963 adev->perf_lock_opts[0] = 0x101;
3964 adev->perf_lock_opts[1] = 0x20E;
3965 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303966
3967 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3968 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003970 adev->platform = platform_init(adev);
3971 if (!adev->platform) {
3972 free(adev->snd_dev_ref_cnt);
3973 free(adev);
3974 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3975 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003976 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003977 return -EINVAL;
3978 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003979
Naresh Tanniru4c630392014-05-12 01:05:52 +05303980 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3981
Eric Laurentc4aef752013-09-12 17:45:53 -07003982 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3983 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3984 if (adev->visualizer_lib == NULL) {
3985 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3986 } else {
3987 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3988 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003989 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003990 "visualizer_hal_start_output");
3991 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003992 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003993 "visualizer_hal_stop_output");
3994 }
3995 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003996 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003997 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003998
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003999 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4000 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4001 if (adev->offload_effects_lib == NULL) {
4002 ALOGE("%s: DLOPEN failed for %s", __func__,
4003 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4004 } else {
4005 ALOGV("%s: DLOPEN successful for %s", __func__,
4006 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4007 adev->offload_effects_start_output =
4008 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4009 "offload_effects_bundle_hal_start_output");
4010 adev->offload_effects_stop_output =
4011 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4012 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004013 adev->offload_effects_set_hpx_state =
4014 (int (*)(bool))dlsym(adev->offload_effects_lib,
4015 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304016 adev->offload_effects_get_parameters =
4017 (void (*)(struct str_parms *, struct str_parms *))
4018 dlsym(adev->offload_effects_lib,
4019 "offload_effects_bundle_get_parameters");
4020 adev->offload_effects_set_parameters =
4021 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4022 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004023 }
4024 }
4025
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004026 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4027 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4028 if (adev->adm_lib == NULL) {
4029 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4030 } else {
4031 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4032 adev->adm_init = (adm_init_t)
4033 dlsym(adev->adm_lib, "adm_init");
4034 adev->adm_deinit = (adm_deinit_t)
4035 dlsym(adev->adm_lib, "adm_deinit");
4036 adev->adm_register_input_stream = (adm_register_input_stream_t)
4037 dlsym(adev->adm_lib, "adm_register_input_stream");
4038 adev->adm_register_output_stream = (adm_register_output_stream_t)
4039 dlsym(adev->adm_lib, "adm_register_output_stream");
4040 adev->adm_deregister_stream = (adm_deregister_stream_t)
4041 dlsym(adev->adm_lib, "adm_deregister_stream");
4042 adev->adm_request_focus = (adm_request_focus_t)
4043 dlsym(adev->adm_lib, "adm_request_focus");
4044 adev->adm_abandon_focus = (adm_abandon_focus_t)
4045 dlsym(adev->adm_lib, "adm_abandon_focus");
4046 }
4047 }
4048
Mingming Yin514a8bc2014-07-29 15:22:21 -07004049 adev->bt_wb_speech_enabled = false;
4050
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004051 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 *device = &adev->device.common;
4053
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004054 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4055 &adev->streams_output_cfg_list);
4056
Kiran Kandi910e1862013-10-29 13:29:42 -07004057 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004058
4059 char value[PROPERTY_VALUE_MAX];
4060 int trial;
4061 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4062 trial = atoi(value);
4063 if (period_size_is_plausible_for_low_latency(trial)) {
4064 pcm_config_low_latency.period_size = trial;
4065 pcm_config_low_latency.start_threshold = trial / 4;
4066 pcm_config_low_latency.avail_min = trial / 4;
4067 configured_low_latency_capture_period_size = trial;
4068 }
4069 }
4070 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4071 trial = atoi(value);
4072 if (period_size_is_plausible_for_low_latency(trial)) {
4073 configured_low_latency_capture_period_size = trial;
4074 }
4075 }
4076
vivek mehta446c3962015-09-14 10:57:35 -07004077 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004078 pthread_mutex_unlock(&adev_init_lock);
4079
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004080 if (adev->adm_init)
4081 adev->adm_data = adev->adm_init();
4082
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304083 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004084 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 return 0;
4086}
4087
4088static struct hw_module_methods_t hal_module_methods = {
4089 .open = adev_open,
4090};
4091
4092struct audio_module HAL_MODULE_INFO_SYM = {
4093 .common = {
4094 .tag = HARDWARE_MODULE_TAG,
4095 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4096 .hal_api_version = HARDWARE_HAL_API_VERSION,
4097 .id = AUDIO_HARDWARE_MODULE_ID,
4098 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004099 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 .methods = &hal_module_methods,
4101 },
4102};