blob: d10bc18e075fe86148e8b580913f37fcebbf8150 [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
vivek mehtaa76401a2015-04-24 14:12:15 -0700252__attribute__ ((visibility ("default")))
253bool audio_hw_send_gain_dep_calibration(int level) {
254 bool ret_val = false;
255 ALOGV("%s: called ... ", __func__);
256
257 pthread_mutex_lock(&adev_init_lock);
258
259 if (adev != NULL && adev->platform != NULL) {
260 pthread_mutex_lock(&adev->lock);
261 ret_val = platform_send_gain_dep_cal(adev->platform, level);
262 pthread_mutex_unlock(&adev->lock);
263 } else {
264 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
265 }
266
267 pthread_mutex_unlock(&adev_init_lock);
268
269 return ret_val;
270}
271
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800272static int check_and_set_gapless_mode(struct audio_device *adev) {
273
274
275 char value[PROPERTY_VALUE_MAX] = {0};
276 bool gapless_enabled = false;
277 const char *mixer_ctl_name = "Compress Gapless Playback";
278 struct mixer_ctl *ctl;
279
280 ALOGV("%s:", __func__);
281 property_get("audio.offload.gapless.enabled", value, NULL);
282 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
283
284 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
285 if (!ctl) {
286 ALOGE("%s: Could not get ctl for mixer cmd - %s",
287 __func__, mixer_ctl_name);
288 return -EINVAL;
289 }
290
291 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
292 ALOGE("%s: Could not set gapless mode %d",
293 __func__, gapless_enabled);
294 return -EINVAL;
295 }
296 return 0;
297}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700299static bool is_supported_format(audio_format_t format)
300{
Eric Laurent86e17132013-09-12 17:49:30 -0700301 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530302 format == AUDIO_FORMAT_AAC_LC ||
303 format == AUDIO_FORMAT_AAC_HE_V1 ||
304 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530305 format == AUDIO_FORMAT_AAC_ADTS_LC ||
306 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700310 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800311 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530312 format == AUDIO_FORMAT_ALAC ||
313 format == AUDIO_FORMAT_APE ||
314 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800315 format == AUDIO_FORMAT_WMA ||
316 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800317 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700318
319 return false;
320}
321
322static int get_snd_codec_id(audio_format_t format)
323{
324 int id = 0;
325
Ashish Jainf9b78162014-08-25 20:36:25 +0530326 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700327 case AUDIO_FORMAT_MP3:
328 id = SND_AUDIOCODEC_MP3;
329 break;
330 case AUDIO_FORMAT_AAC:
331 id = SND_AUDIOCODEC_AAC;
332 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530333 case AUDIO_FORMAT_AAC_ADTS:
334 id = SND_AUDIOCODEC_AAC;
335 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530336 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700337 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800338 id = SND_AUDIOCODEC_PCM;
339 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700340 case AUDIO_FORMAT_FLAC:
341 id = SND_AUDIOCODEC_FLAC;
342 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530343 case AUDIO_FORMAT_ALAC:
344 id = SND_AUDIOCODEC_ALAC;
345 break;
346 case AUDIO_FORMAT_APE:
347 id = SND_AUDIOCODEC_APE;
348 break;
349 case AUDIO_FORMAT_VORBIS:
350 id = SND_AUDIOCODEC_VORBIS;
351 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800352 case AUDIO_FORMAT_WMA:
353 id = SND_AUDIOCODEC_WMA;
354 break;
355 case AUDIO_FORMAT_WMA_PRO:
356 id = SND_AUDIOCODEC_WMA_PRO;
357 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700358 default:
Mingming Yin90310102013-11-13 16:57:00 -0800359 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 }
361
362 return id;
363}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800364
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530365int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530366{
367 int snd_scard_state;
368
369 if (!adev)
370 return SND_CARD_STATE_OFFLINE;
371
372 pthread_mutex_lock(&adev->snd_card_status.lock);
373 snd_scard_state = adev->snd_card_status.state;
374 pthread_mutex_unlock(&adev->snd_card_status.lock);
375
376 return snd_scard_state;
377}
378
379static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
380{
381 if (!adev)
382 return -ENOSYS;
383
384 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700385 if (adev->snd_card_status.state != snd_scard_state) {
386 adev->snd_card_status.state = snd_scard_state;
387 platform_snd_card_update(adev->platform, snd_scard_state);
388 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530389 pthread_mutex_unlock(&adev->snd_card_status.lock);
390
391 return 0;
392}
393
Avinash Vaish71a8b972014-07-24 15:36:33 +0530394static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
395 struct audio_usecase *uc_info)
396{
397 struct listnode *node;
398 struct audio_usecase *usecase;
399
400 if (uc_info == NULL)
401 return -EINVAL;
402
403 /* Re-route all voice usecases on the shared backend other than the
404 specified usecase to new snd devices */
405 list_for_each(node, &adev->usecase_list) {
406 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800407 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530408 enable_audio_route(adev, usecase);
409 }
410 return 0;
411}
412
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700413int pcm_ioctl(struct pcm *pcm, int request, ...)
414{
415 va_list ap;
416 void * arg;
417 int pcm_fd = *(int*)pcm;
418
419 va_start(ap, request);
420 arg = va_arg(ap, void *);
421 va_end(ap);
422
423 return ioctl(pcm_fd, request, arg);
424}
425
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700426int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700427 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700429 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700430 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800431
432 if (usecase == NULL)
433 return -EINVAL;
434
435 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
436
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800437 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700438 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800442#ifdef DS1_DOLBY_DAP_ENABLED
443 audio_extn_dolby_set_dmid(adev);
444 audio_extn_dolby_set_endpoint(adev);
445#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700446 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700447 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530448 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700449 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530450 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800451 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700452 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700453 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700454 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455 ALOGV("%s: exit", __func__);
456 return 0;
457}
458
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700459int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700460 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700462 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700463 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800464
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530465 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466 return -EINVAL;
467
468 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 if (usecase->type == PCM_CAPTURE)
470 snd_device = usecase->in_snd_device;
471 else
472 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800473 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700474 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700475 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700476 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700477 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530478 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479 ALOGV("%s: exit", __func__);
480 return 0;
481}
482
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700483int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700484 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700486 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
487
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800488 if (snd_device < SND_DEVICE_MIN ||
489 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800490 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800491 return -EINVAL;
492 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700493
494 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700495
496 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
497 ALOGE("%s: Invalid sound device returned", __func__);
498 return -EINVAL;
499 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700500 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700501 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700502 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700503 return 0;
504 }
505
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530506
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700507 if (audio_extn_spkr_prot_is_enabled())
508 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700509 /* start usb playback thread */
510 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
511 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
512 audio_extn_usb_start_playback(adev);
513
514 /* start usb capture thread */
515 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
516 audio_extn_usb_start_capture(adev);
517
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800518 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
519 audio_extn_spkr_prot_is_enabled()) {
520 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700521 adev->snd_dev_ref_cnt[snd_device]--;
522 return -EINVAL;
523 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200524 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800525 if (audio_extn_spkr_prot_start_processing(snd_device)) {
526 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200527 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800528 return -EINVAL;
529 }
530 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700531 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700532 /* due to the possibility of calibration overwrite between listen
533 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700534 audio_extn_sound_trigger_update_device_status(snd_device,
535 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530536 audio_extn_listen_update_device_status(snd_device,
537 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700538 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700539 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700540 audio_extn_sound_trigger_update_device_status(snd_device,
541 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530542 audio_extn_listen_update_device_status(snd_device,
543 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700544 return -EINVAL;
545 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300546 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700547 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530548
549 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
550 !adev->native_playback_enabled &&
551 audio_is_true_native_stream_active(adev)) {
552 ALOGD("%s: %d: napb: enabling native mode in hardware",
553 __func__, __LINE__);
554 audio_route_apply_and_update_path(adev->audio_route,
555 "true-native-mode");
556 adev->native_playback_enabled = true;
557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559 return 0;
560}
561
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700562int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700563 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800564{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700565 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
566
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800567 if (snd_device < SND_DEVICE_MIN ||
568 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800569 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800570 return -EINVAL;
571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
573 ALOGE("%s: device ref cnt is already 0", __func__);
574 return -EINVAL;
575 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700578
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700579 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
580 ALOGE("%s: Invalid sound device returned", __func__);
581 return -EINVAL;
582 }
583
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700584 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700585 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800586 /* exit usb play back thread */
587 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
588 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
589 audio_extn_usb_stop_playback();
590
591 /* exit usb capture thread */
592 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700593 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800594
595 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
596 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700597 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300598 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700599 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700601
Ashish Jain81eb2a82015-05-13 10:52:34 +0530602 if (snd_device == SND_DEVICE_OUT_HDMI)
603 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530604 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
605 adev->native_playback_enabled) {
606 ALOGD("%s: %d: napb: disabling native mode in hardware",
607 __func__, __LINE__);
608 audio_route_reset_and_update_path(adev->audio_route,
609 "true-native-mode");
610 adev->native_playback_enabled = false;
611 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530612
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200613 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700614 audio_extn_sound_trigger_update_device_status(snd_device,
615 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530616 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800617 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800620 return 0;
621}
622
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530624 struct audio_usecase *uc_info,
625 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626{
627 struct listnode *node;
628 struct audio_usecase *usecase;
629 bool switch_device[AUDIO_USECASE_MAX];
630 int i, num_uc_to_switch = 0;
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530631 int backend_idx = DEFAULT_CODEC_BACKEND;
632 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633
634 /*
635 * This function is to make sure that all the usecases that are active on
636 * the hardware codec backend are always routed to any one device that is
637 * handled by the hardware codec.
638 * For example, if low-latency and deep-buffer usecases are currently active
639 * on speaker and out_set_parameters(headset) is received on low-latency
640 * output, then we have to make sure deep-buffer is also switched to headset,
641 * because of the limitation that both the devices cannot be enabled
642 * at the same time as they share the same backend.
643 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700644 /*
645 * This call is to check if we need to force routing for a particular stream
646 * If there is a backend configuration change for the device when a
647 * new stream starts, then ADM needs to be closed and re-opened with the new
648 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800649 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700650 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
652 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530653
654 ALOGD("%s:becf: force routing %d", __func__, force_routing);
655
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530656 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800658 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800659 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 for (i = 0; i < AUDIO_USECASE_MAX; i++)
661 switch_device[i] = false;
662
663 list_for_each(node, &adev->usecase_list) {
664 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800665
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530666 if (usecase == uc_info)
667 continue;
668 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
669
670 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
671 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
672 __func__, i, backend_idx, usecase_backend_idx,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530673 platform_get_snd_device_name(snd_device),
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530674 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800675
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800676 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530677 (usecase->out_snd_device != snd_device || force_routing) &&
678 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
679 usecase_backend_idx == backend_idx) {
680 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
681 __func__, use_case_table[usecase->id],
682 platform_get_snd_device_name(usecase->out_snd_device));
683 disable_audio_route(adev, usecase);
684 switch_device[usecase->id] = true;
685 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 }
687 }
688
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530689 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
690 num_uc_to_switch);
691
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700692 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700693 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530695 /* Make sure the previous devices to be disabled first and then enable the
696 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700697 list_for_each(node, &adev->usecase_list) {
698 usecase = node_to_item(node, struct audio_usecase, list);
699 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700700 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700701 }
702 }
703
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700704 list_for_each(node, &adev->usecase_list) {
705 usecase = node_to_item(node, struct audio_usecase, list);
706 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700707 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700708 }
709 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 /* Re-route all the usecases on the shared backend other than the
712 specified usecase to new snd devices */
713 list_for_each(node, &adev->usecase_list) {
714 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530715 /* Update the out_snd_device only before enabling the audio route */
716 if (switch_device[usecase->id]) {
717 usecase->out_snd_device = snd_device;
718 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530719 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530720 use_case_table[usecase->id],
721 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530722 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530723 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 }
725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727}
728
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729static void check_and_route_capture_usecases(struct audio_device *adev,
730 struct audio_usecase *uc_info,
731 snd_device_t snd_device)
732{
733 struct listnode *node;
734 struct audio_usecase *usecase;
735 bool switch_device[AUDIO_USECASE_MAX];
736 int i, num_uc_to_switch = 0;
737
738 /*
739 * This function is to make sure that all the active capture usecases
740 * are always routed to the same input sound device.
741 * For example, if audio-record and voice-call usecases are currently
742 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
743 * is received for voice call then we have to make sure that audio-record
744 * usecase is also switched to earpiece i.e. voice-dmic-ef,
745 * because of the limitation that two devices cannot be enabled
746 * at the same time if they share the same backend.
747 */
748 for (i = 0; i < AUDIO_USECASE_MAX; i++)
749 switch_device[i] = false;
750
751 list_for_each(node, &adev->usecase_list) {
752 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800753 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700755 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700756 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530757 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
758 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700759 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
761 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700762 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700763 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 switch_device[usecase->id] = true;
765 num_uc_to_switch++;
766 }
767 }
768
769 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700770 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700771
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530772 /* Make sure the previous devices to be disabled first and then enable the
773 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 list_for_each(node, &adev->usecase_list) {
775 usecase = node_to_item(node, struct audio_usecase, list);
776 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700777 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800778 }
779 }
780
781 list_for_each(node, &adev->usecase_list) {
782 usecase = node_to_item(node, struct audio_usecase, list);
783 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700784 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700785 }
786 }
787
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700788 /* Re-route all the usecases on the shared backend other than the
789 specified usecase to new snd devices */
790 list_for_each(node, &adev->usecase_list) {
791 usecase = node_to_item(node, struct audio_usecase, list);
792 /* Update the in_snd_device only before enabling the audio route */
793 if (switch_device[usecase->id] ) {
794 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800795 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530796 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700797 }
798 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 }
800}
801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800802/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700803static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700805 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700806 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807
808 switch (channels) {
809 /*
810 * Do not handle stereo output in Multi-channel cases
811 * Stereo case is handled in normal playback path
812 */
813 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700814 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
815 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
816 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
819 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 break;
821 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700822 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
823 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
824 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
828 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829 break;
830 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700831 ALOGE("HDMI does not support multi channel playback");
832 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833 break;
834 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700835 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836}
837
Alexy Josephb1379942016-01-29 15:49:38 -0800838audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800839 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700840{
841 struct audio_usecase *usecase;
842 struct listnode *node;
843
844 list_for_each(node, &adev->usecase_list) {
845 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800846 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847 ALOGV("%s: usecase id %d", __func__, usecase->id);
848 return usecase->id;
849 }
850 }
851 return USECASE_INVALID;
852}
853
Alexy Josephb1379942016-01-29 15:49:38 -0800854struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700855 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856{
857 struct audio_usecase *usecase;
858 struct listnode *node;
859
860 list_for_each(node, &adev->usecase_list) {
861 usecase = node_to_item(node, struct audio_usecase, list);
862 if (usecase->id == uc_id)
863 return usecase;
864 }
865 return NULL;
866}
867
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530868/*
869 * is a true native playback active
870 */
871bool audio_is_true_native_stream_active(struct audio_device *adev)
872{
873 bool active = false;
874 int i = 0;
875 struct listnode *node;
876
877 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
878 ALOGV("%s:napb: not in true mode or non hdphones device",
879 __func__);
880 active = false;
881 goto exit;
882 }
883
884 list_for_each(node, &adev->usecase_list) {
885 struct audio_usecase *uc;
886 uc = node_to_item(node, struct audio_usecase, list);
887 struct stream_out *curr_out =
888 (struct stream_out*) uc->stream.out;
889
890 if (curr_out && PCM_PLAYBACK == uc->type) {
891 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
892 "(%d) device %s", __func__, i++, use_case_table[uc->id],
893 uc->id, curr_out->sample_rate,
894 curr_out->bit_width,
895 platform_get_snd_device_name(uc->out_snd_device));
896
897 if (is_offload_usecase(uc->id) &&
898 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
899 active = true;
900 ALOGD("%s:napb:native stream detected", __func__);
901 }
902 }
903 }
904exit:
905 return active;
906}
907
908
909static bool force_device_switch(struct audio_usecase *usecase)
910{
911 bool ret = false;
912 bool is_it_true_mode = false;
913
914 if (is_offload_usecase(usecase->id) &&
915 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800916 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
917 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
918 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530919 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
920 if ((is_it_true_mode && !adev->native_playback_enabled) ||
921 (!is_it_true_mode && adev->native_playback_enabled)){
922 ret = true;
923 ALOGD("napb: time to toggle native mode");
924 }
925 }
926
927 return ret;
928}
929
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700930int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800931{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800932 snd_device_t out_snd_device = SND_DEVICE_NONE;
933 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700934 struct audio_usecase *usecase = NULL;
935 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800936 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800937 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800938 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800940
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530941 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
942
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 usecase = get_usecase_from_list(adev, uc_id);
944 if (usecase == NULL) {
945 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
946 return -EINVAL;
947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800949 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800950 (usecase->type == VOIP_CALL) ||
951 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800953 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700954 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700955 usecase->devices = usecase->stream.out->devices;
956 } else {
957 /*
958 * If the voice call is active, use the sound devices of voice call usecase
959 * so that it would not result any device switch. All the usecases will
960 * be switched to new device when select_devices() is called for voice call
961 * usecase. This is to avoid switching devices for voice call when
962 * check_usecases_codec_backend() is called below.
963 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800964 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700965 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800966 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700967 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
968 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969 in_snd_device = vc_usecase->in_snd_device;
970 out_snd_device = vc_usecase->out_snd_device;
971 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800972 } else if (voice_extn_compress_voip_is_active(adev)) {
973 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700974 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530975 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700976 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800977 in_snd_device = voip_usecase->in_snd_device;
978 out_snd_device = voip_usecase->out_snd_device;
979 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800980 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800981 hfp_ucid = audio_extn_hfp_get_usecase();
982 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700983 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800984 in_snd_device = hfp_usecase->in_snd_device;
985 out_snd_device = hfp_usecase->out_snd_device;
986 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 }
988 if (usecase->type == PCM_PLAYBACK) {
989 usecase->devices = usecase->stream.out->devices;
990 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700991 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700992 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800993 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700994 if (usecase->stream.out == adev->primary_output &&
995 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800996 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700997 select_devices(adev, adev->active_input->usecase);
998 }
999 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001000 } else if (usecase->type == PCM_CAPTURE) {
1001 usecase->devices = usecase->stream.in->device;
1002 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001003 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001004 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001005 if (adev->active_input &&
1006 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301007 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1008 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1009 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001010 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001011 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001012 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1013 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001014 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001015 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001016 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017 }
1018 }
1019
1020 if (out_snd_device == usecase->out_snd_device &&
1021 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301022
1023 if (!force_device_switch(usecase))
1024 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 }
1026
sangwoobc677242013-08-08 16:53:43 +09001027 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001028 out_snd_device, platform_get_snd_device_name(out_snd_device),
1029 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 /*
1032 * Limitation: While in call, to do a device switch we need to disable
1033 * and enable both RX and TX devices though one of them is same as current
1034 * device.
1035 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001036 if ((usecase->type == VOICE_CALL) &&
1037 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1038 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001039 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001040 }
1041
1042 if (((usecase->type == VOICE_CALL) ||
1043 (usecase->type == VOIP_CALL)) &&
1044 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1045 /* Disable sidetone only if voice/voip call already exists */
1046 if (voice_is_call_state_active(adev) ||
1047 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001048 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001049 }
1050
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051 /* Disable current sound devices */
1052 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001053 disable_audio_route(adev, usecase);
1054 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 }
1056
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001058 disable_audio_route(adev, usecase);
1059 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 }
1061
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001062 /* Applicable only on the targets that has external modem.
1063 * New device information should be sent to modem before enabling
1064 * the devices to reduce in-call device switch time.
1065 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001066 if ((usecase->type == VOICE_CALL) &&
1067 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1068 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001069 status = platform_switch_voice_call_enable_device_config(adev->platform,
1070 out_snd_device,
1071 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001072 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001073
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 /* Enable new sound devices */
1075 if (out_snd_device != SND_DEVICE_NONE) {
1076 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1077 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001078 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079 }
1080
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001081 if (in_snd_device != SND_DEVICE_NONE) {
1082 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001083 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085
Avinash Vaish71a8b972014-07-24 15:36:33 +05301086 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001087 status = platform_switch_voice_call_device_post(adev->platform,
1088 out_snd_device,
1089 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301090 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001091 /* Enable sidetone only if voice/voip call already exists */
1092 if (voice_is_call_state_active(adev) ||
1093 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001094 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301095 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001096
sangwoo170731f2013-06-08 15:36:36 +09001097 usecase->in_snd_device = in_snd_device;
1098 usecase->out_snd_device = out_snd_device;
1099
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301100 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001101 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301102 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001103 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301104 usecase->stream.out->flags,
1105 usecase->stream.out->format,
1106 usecase->stream.out->sample_rate,
1107 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301108 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301109 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001110 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301111 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001112
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001114
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001115 /* Applicable only on the targets that has external modem.
1116 * Enable device command should be sent to modem only after
1117 * enabling voice call mixer controls
1118 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001119 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001120 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1121 out_snd_device,
1122 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301123 ALOGD("%s: done",__func__);
1124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125 return status;
1126}
1127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128static int stop_input_stream(struct stream_in *in)
1129{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301130 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131 struct audio_usecase *uc_info;
1132 struct audio_device *adev = in->dev;
1133
Eric Laurentc8400632013-02-14 19:04:54 -08001134 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001135
Eric Laurent994a6932013-07-17 11:51:42 -07001136 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138 uc_info = get_usecase_from_list(adev, in->usecase);
1139 if (uc_info == NULL) {
1140 ALOGE("%s: Could not find the usecase (%d) in the list",
1141 __func__, in->usecase);
1142 return -EINVAL;
1143 }
1144
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001145 /* Close in-call recording streams */
1146 voice_check_and_stop_incall_rec_usecase(adev, in);
1147
Eric Laurent150dbfe2013-02-27 14:31:02 -08001148 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001149 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150
1151 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001152 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001154 list_remove(&uc_info->list);
1155 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156
Eric Laurent994a6932013-07-17 11:51:42 -07001157 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158 return ret;
1159}
1160
1161int start_input_stream(struct stream_in *in)
1162{
1163 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001164 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165 struct audio_usecase *uc_info;
1166 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301167 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168
Mingming Yin2664a5b2015-09-03 10:53:11 -07001169 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1170 if (get_usecase_from_list(adev, usecase) == NULL)
1171 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301172 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1173 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001174
Naresh Tanniru80659832014-06-04 18:17:56 +05301175
1176 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301177 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301178 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301179 goto error_config;
1180 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301181
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001182 /* Check if source matches incall recording usecase criteria */
1183 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1184 if (ret)
1185 goto error_config;
1186 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001187 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1188
1189 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1190 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1191 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1192 goto error_config;
1193 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001194
Eric Laurentb23d5282013-05-14 15:27:20 -07001195 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001196 if (in->pcm_device_id < 0) {
1197 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1198 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001199 ret = -EINVAL;
1200 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202
1203 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001205
1206 if (!uc_info) {
1207 ret = -ENOMEM;
1208 goto error_config;
1209 }
1210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001211 uc_info->id = in->usecase;
1212 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001213 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001214 uc_info->devices = in->device;
1215 uc_info->in_snd_device = SND_DEVICE_NONE;
1216 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001218 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301219 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1220 adev->perf_lock_opts,
1221 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001222 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223
Eric Laurentc8400632013-02-14 19:04:54 -08001224 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001225 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1226
1227 unsigned int flags = PCM_IN;
1228 unsigned int pcm_open_retry_count = 0;
1229
1230 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1231 flags |= PCM_MMAP | PCM_NOIRQ;
1232 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1233 }
1234
1235 while (1) {
1236 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1237 flags, &in->config);
1238 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1239 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1240 if (in->pcm != NULL) {
1241 pcm_close(in->pcm);
1242 in->pcm = NULL;
1243 }
1244 if (pcm_open_retry_count-- == 0) {
1245 ret = -EIO;
1246 goto error_open;
1247 }
1248 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1249 continue;
1250 }
1251 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001253
1254 ALOGV("%s: pcm_prepare", __func__);
1255 ret = pcm_prepare(in->pcm);
1256 if (ret < 0) {
1257 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1258 pcm_close(in->pcm);
1259 in->pcm = NULL;
1260 goto error_open;
1261 }
1262
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301263 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001264 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001265
Eric Laurentc8400632013-02-14 19:04:54 -08001266 return ret;
1267
1268error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301269 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001271error_config:
1272 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301273 /*
1274 * sleep 50ms to allow sufficient time for kernel
1275 * drivers to recover incases like SSR.
1276 */
1277 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001279
1280 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281}
1282
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001283void lock_input_stream(struct stream_in *in)
1284{
1285 pthread_mutex_lock(&in->pre_lock);
1286 pthread_mutex_lock(&in->lock);
1287 pthread_mutex_unlock(&in->pre_lock);
1288}
1289
1290void lock_output_stream(struct stream_out *out)
1291{
1292 pthread_mutex_lock(&out->pre_lock);
1293 pthread_mutex_lock(&out->lock);
1294 pthread_mutex_unlock(&out->pre_lock);
1295}
1296
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001297/* must be called with out->lock locked */
1298static int send_offload_cmd_l(struct stream_out* out, int command)
1299{
1300 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1301
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001302 if (!cmd) {
1303 ALOGE("failed to allocate mem for command 0x%x", command);
1304 return -ENOMEM;
1305 }
1306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001307 ALOGVV("%s %d", __func__, command);
1308
1309 cmd->cmd = command;
1310 list_add_tail(&out->offload_cmd_list, &cmd->node);
1311 pthread_cond_signal(&out->offload_cond);
1312 return 0;
1313}
1314
1315/* must be called iwth out->lock locked */
1316static void stop_compressed_output_l(struct stream_out *out)
1317{
1318 out->offload_state = OFFLOAD_STATE_IDLE;
1319 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001320 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001321 if (out->compr != NULL) {
1322 compress_stop(out->compr);
1323 while (out->offload_thread_blocked) {
1324 pthread_cond_wait(&out->cond, &out->lock);
1325 }
1326 }
1327}
1328
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001329bool is_offload_usecase(audio_usecase_t uc_id)
1330{
1331 unsigned int i;
1332 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1333 if (uc_id == offload_usecases[i])
1334 return true;
1335 }
1336 return false;
1337}
1338
vivek mehta446c3962015-09-14 10:57:35 -07001339static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001340{
vivek mehta446c3962015-09-14 10:57:35 -07001341 audio_usecase_t ret_uc = USECASE_INVALID;
1342 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001343 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001344 if (!adev->multi_offload_enable) {
1345 if (is_direct_pcm)
1346 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1347 else
1348 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001349
vivek mehta446c3962015-09-14 10:57:35 -07001350 pthread_mutex_lock(&adev->lock);
1351 if (get_usecase_from_list(adev, ret_uc) != NULL)
1352 ret_uc = USECASE_INVALID;
1353 pthread_mutex_unlock(&adev->lock);
1354
1355 return ret_uc;
1356 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001357
1358 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001359 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1360 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1361 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1362 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001363 break;
1364 }
1365 }
vivek mehta446c3962015-09-14 10:57:35 -07001366
1367 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1368 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001369}
1370
1371static void free_offload_usecase(struct audio_device *adev,
1372 audio_usecase_t uc_id)
1373{
vivek mehta446c3962015-09-14 10:57:35 -07001374 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001375 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001376
1377 if (!adev->multi_offload_enable)
1378 return;
1379
1380 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1381 if (offload_usecases[offload_uc_index] == uc_id) {
1382 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001383 break;
1384 }
1385 }
1386 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1387}
1388
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001389static void *offload_thread_loop(void *context)
1390{
1391 struct stream_out *out = (struct stream_out *) context;
1392 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001393 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001394
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001395 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1396 set_sched_policy(0, SP_FOREGROUND);
1397 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1398
1399 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001400 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001401 for (;;) {
1402 struct offload_cmd *cmd = NULL;
1403 stream_callback_event_t event;
1404 bool send_callback = false;
1405
1406 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1407 __func__, list_empty(&out->offload_cmd_list),
1408 out->offload_state);
1409 if (list_empty(&out->offload_cmd_list)) {
1410 ALOGV("%s SLEEPING", __func__);
1411 pthread_cond_wait(&out->offload_cond, &out->lock);
1412 ALOGV("%s RUNNING", __func__);
1413 continue;
1414 }
1415
1416 item = list_head(&out->offload_cmd_list);
1417 cmd = node_to_item(item, struct offload_cmd, node);
1418 list_remove(item);
1419
1420 ALOGVV("%s STATE %d CMD %d out->compr %p",
1421 __func__, out->offload_state, cmd->cmd, out->compr);
1422
1423 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1424 free(cmd);
1425 break;
1426 }
1427
1428 if (out->compr == NULL) {
1429 ALOGE("%s: Compress handle is NULL", __func__);
1430 pthread_cond_signal(&out->cond);
1431 continue;
1432 }
1433 out->offload_thread_blocked = true;
1434 pthread_mutex_unlock(&out->lock);
1435 send_callback = false;
1436 switch(cmd->cmd) {
1437 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001438 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001439 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001440 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001441 send_callback = true;
1442 event = STREAM_CBK_EVENT_WRITE_READY;
1443 break;
1444 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001445 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301446 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001447 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301448 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001449 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301450 if (ret < 0)
1451 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301452 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301453 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001454 compress_drain(out->compr);
1455 else
1456 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301457 if (ret != -ENETRESET) {
1458 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301459 pthread_mutex_lock(&out->lock);
1460 out->send_new_metadata = 1;
1461 out->send_next_track_params = true;
1462 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301463 event = STREAM_CBK_EVENT_DRAIN_READY;
1464 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1465 } else
1466 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467 break;
1468 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001469 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001471 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001472 send_callback = true;
1473 event = STREAM_CBK_EVENT_DRAIN_READY;
1474 break;
1475 default:
1476 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1477 break;
1478 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001479 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480 out->offload_thread_blocked = false;
1481 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001482 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001483 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001484 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001485 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001486 free(cmd);
1487 }
1488
1489 pthread_cond_signal(&out->cond);
1490 while (!list_empty(&out->offload_cmd_list)) {
1491 item = list_head(&out->offload_cmd_list);
1492 list_remove(item);
1493 free(node_to_item(item, struct offload_cmd, node));
1494 }
1495 pthread_mutex_unlock(&out->lock);
1496
1497 return NULL;
1498}
1499
1500static int create_offload_callback_thread(struct stream_out *out)
1501{
1502 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1503 list_init(&out->offload_cmd_list);
1504 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1505 offload_thread_loop, out);
1506 return 0;
1507}
1508
1509static int destroy_offload_callback_thread(struct stream_out *out)
1510{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001512 stop_compressed_output_l(out);
1513 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1514
1515 pthread_mutex_unlock(&out->lock);
1516 pthread_join(out->offload_thread, (void **) NULL);
1517 pthread_cond_destroy(&out->offload_cond);
1518
1519 return 0;
1520}
1521
Eric Laurent07eeafd2013-10-06 12:52:49 -07001522static bool allow_hdmi_channel_config(struct audio_device *adev)
1523{
1524 struct listnode *node;
1525 struct audio_usecase *usecase;
1526 bool ret = true;
1527
1528 list_for_each(node, &adev->usecase_list) {
1529 usecase = node_to_item(node, struct audio_usecase, list);
1530 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1531 /*
1532 * If voice call is already existing, do not proceed further to avoid
1533 * disabling/enabling both RX and TX devices, CSD calls, etc.
1534 * Once the voice call done, the HDMI channels can be configured to
1535 * max channels of remaining use cases.
1536 */
1537 if (usecase->id == USECASE_VOICE_CALL) {
1538 ALOGD("%s: voice call is active, no change in HDMI channels",
1539 __func__);
1540 ret = false;
1541 break;
1542 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1543 ALOGD("%s: multi channel playback is active, "
1544 "no change in HDMI channels", __func__);
1545 ret = false;
1546 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001547 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001548 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001549 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1550 ", no change in HDMI channels", __func__,
1551 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001552 ret = false;
1553 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001554 }
1555 }
1556 }
1557 return ret;
1558}
1559
1560static int check_and_set_hdmi_channels(struct audio_device *adev,
1561 unsigned int channels)
1562{
1563 struct listnode *node;
1564 struct audio_usecase *usecase;
1565
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001566 unsigned int supported_channels = platform_edid_get_max_channels(
1567 adev->platform);
1568 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001569 /* Check if change in HDMI channel config is allowed */
1570 if (!allow_hdmi_channel_config(adev))
1571 return 0;
1572
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001573 if (channels > supported_channels)
1574 channels = supported_channels;
1575
Eric Laurent07eeafd2013-10-06 12:52:49 -07001576 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001577 ALOGD("%s: Requested channels are same as current channels(%d)",
1578 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001579 return 0;
1580 }
1581
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001582 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001583 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001584 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001585 adev->cur_hdmi_channels = channels;
1586
1587 /*
1588 * Deroute all the playback streams routed to HDMI so that
1589 * the back end is deactivated. Note that backend will not
1590 * be deactivated if any one stream is connected to it.
1591 */
1592 list_for_each(node, &adev->usecase_list) {
1593 usecase = node_to_item(node, struct audio_usecase, list);
1594 if (usecase->type == PCM_PLAYBACK &&
1595 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001596 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001597 }
1598 }
1599
1600 /*
1601 * Enable all the streams disabled above. Now the HDMI backend
1602 * will be activated with new channel configuration
1603 */
1604 list_for_each(node, &adev->usecase_list) {
1605 usecase = node_to_item(node, struct audio_usecase, list);
1606 if (usecase->type == PCM_PLAYBACK &&
1607 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001608 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001609 }
1610 }
1611
1612 return 0;
1613}
1614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615static int stop_output_stream(struct stream_out *out)
1616{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301617 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 struct audio_usecase *uc_info;
1619 struct audio_device *adev = out->dev;
1620
Eric Laurent994a6932013-07-17 11:51:42 -07001621 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 uc_info = get_usecase_from_list(adev, out->usecase);
1624 if (uc_info == NULL) {
1625 ALOGE("%s: Could not find the usecase (%d) in the list",
1626 __func__, out->usecase);
1627 return -EINVAL;
1628 }
1629
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001630 if (is_offload_usecase(out->usecase) &&
1631 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001632 if (adev->visualizer_stop_output != NULL)
1633 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001634
1635 audio_extn_dts_remove_state_notifier_node(out->usecase);
1636
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001637 if (adev->offload_effects_stop_output != NULL)
1638 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1639 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001640
Eric Laurent150dbfe2013-02-27 14:31:02 -08001641 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001642 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643
1644 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001645 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001647 list_remove(&uc_info->list);
1648 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001650 if (is_offload_usecase(out->usecase) &&
1651 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1652 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1653 ALOGV("Disable passthrough , reset mixer to pcm");
1654 /* NO_PASSTHROUGH */
1655 out->compr_config.codec->compr_passthr = 0;
1656 audio_extn_dolby_set_hdmi_config(adev, out);
1657 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1658 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001659 /* Must be called after removing the usecase from list */
1660 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1661 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1662
Eric Laurent994a6932013-07-17 11:51:42 -07001663 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 return ret;
1665}
1666
1667int start_output_stream(struct stream_out *out)
1668{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001670 int sink_channels = 0;
1671 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 struct audio_usecase *uc_info;
1673 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301674 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001676 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1677 ret = -EINVAL;
1678 goto error_config;
1679 }
1680
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301681 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1682 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1683 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301684
Naresh Tanniru80659832014-06-04 18:17:56 +05301685 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301686 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301687 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301688 goto error_config;
1689 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301690
Eric Laurentb23d5282013-05-14 15:27:20 -07001691 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692 if (out->pcm_device_id < 0) {
1693 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1694 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001695 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001696 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 }
1698
1699 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001700
1701 if (!uc_info) {
1702 ret = -ENOMEM;
1703 goto error_config;
1704 }
1705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706 uc_info->id = out->usecase;
1707 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001708 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 uc_info->devices = out->devices;
1710 uc_info->in_snd_device = SND_DEVICE_NONE;
1711 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001712 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001713 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001714 if (is_offload_usecase(out->usecase)) {
1715 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001716 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1717 }
1718 }
Mingming Yin9c041392014-05-01 15:37:31 -07001719 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1720 if (!strncmp("true", prop_value, 4)) {
1721 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001722 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1723 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001724 check_and_set_hdmi_channels(adev, sink_channels);
1725 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001726 if (is_offload_usecase(out->usecase)) {
1727 unsigned int ch_count = out->compr_config.codec->ch_in;
1728 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1729 /* backend channel config for passthrough stream is stereo */
1730 ch_count = 2;
1731 check_and_set_hdmi_channels(adev, ch_count);
1732 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001733 check_and_set_hdmi_channels(adev, out->config.channels);
1734 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001735 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001736 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001737 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301739 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1740 adev->perf_lock_opts,
1741 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001742 select_devices(adev, out->usecase);
1743
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001744 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1745 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001746 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001747 unsigned int flags = PCM_OUT;
1748 unsigned int pcm_open_retry_count = 0;
1749 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1750 flags |= PCM_MMAP | PCM_NOIRQ;
1751 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1752 } else
1753 flags |= PCM_MONOTONIC;
1754
1755 while (1) {
1756 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1757 flags, &out->config);
1758 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1759 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1760 if (out->pcm != NULL) {
1761 pcm_close(out->pcm);
1762 out->pcm = NULL;
1763 }
1764 if (pcm_open_retry_count-- == 0) {
1765 ret = -EIO;
1766 goto error_open;
1767 }
1768 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1769 continue;
1770 }
1771 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001773
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001774 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1775 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001776
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001777 ALOGV("%s: pcm_prepare", __func__);
1778 if (pcm_is_ready(out->pcm)) {
1779 ret = pcm_prepare(out->pcm);
1780 if (ret < 0) {
1781 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1782 pcm_close(out->pcm);
1783 out->pcm = NULL;
1784 goto error_open;
1785 }
1786 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001787 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001788 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1789 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001791 out->compr = compress_open(adev->snd_card,
1792 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 COMPRESS_IN, &out->compr_config);
1794 if (out->compr && !is_compress_ready(out->compr)) {
1795 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1796 compress_close(out->compr);
1797 out->compr = NULL;
1798 ret = -EIO;
1799 goto error_open;
1800 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301801 /* compress_open sends params of the track, so reset the flag here */
1802 out->is_compr_metadata_avail = false;
1803
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 if (out->offload_callback)
1805 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001806
Fred Oh3f43e742015-03-04 18:42:34 -08001807 /* Since small bufs uses blocking writes, a write will be blocked
1808 for the default max poll time (20s) in the event of an SSR.
1809 Reduce the poll time to observe and deal with SSR faster.
1810 */
1811 if (out->use_small_bufs) {
1812 compress_set_max_poll_wait(out->compr, 1000);
1813 }
1814
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001815 audio_extn_dts_create_state_notifier_node(out->usecase);
1816 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1817 popcount(out->channel_mask),
1818 out->playback_started);
1819
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001820#ifdef DS1_DOLBY_DDP_ENABLED
1821 if (audio_extn_is_dolby_format(out->format))
1822 audio_extn_dolby_send_ddp_endp_params(adev);
1823#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001824 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1825 if (adev->visualizer_start_output != NULL)
1826 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1827 if (adev->offload_effects_start_output != NULL)
1828 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001829 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001830 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301832 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001833 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001836error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301837 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001839error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301840 /*
1841 * sleep 50ms to allow sufficient time for kernel
1842 * drivers to recover incases like SSR.
1843 */
1844 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001845 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846}
1847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848static int check_input_parameters(uint32_t sample_rate,
1849 audio_format_t format,
1850 int channel_count)
1851{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001852 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001854 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001855 !voice_extn_compress_voip_is_format_supported(format) &&
1856 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001857
1858 switch (channel_count) {
1859 case 1:
1860 case 2:
1861 case 6:
1862 break;
1863 default:
1864 ret = -EINVAL;
1865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
1867 switch (sample_rate) {
1868 case 8000:
1869 case 11025:
1870 case 12000:
1871 case 16000:
1872 case 22050:
1873 case 24000:
1874 case 32000:
1875 case 44100:
1876 case 48000:
1877 break;
1878 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001879 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 }
1881
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001882 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883}
1884
1885static size_t get_input_buffer_size(uint32_t sample_rate,
1886 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001887 int channel_count,
1888 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889{
1890 size_t size = 0;
1891
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001892 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1893 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001895 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001896 if (is_low_latency)
1897 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001898 /* ToDo: should use frame_size computed based on the format and
1899 channel_count here. */
1900 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001901
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001902 /* make sure the size is multiple of 32 bytes
1903 * At 48 kHz mono 16-bit PCM:
1904 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1905 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1906 */
1907 size += 0x1f;
1908 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001909
1910 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911}
1912
1913static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1914{
1915 struct stream_out *out = (struct stream_out *)stream;
1916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918}
1919
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001920static int out_set_sample_rate(struct audio_stream *stream __unused,
1921 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922{
1923 return -ENOSYS;
1924}
1925
1926static size_t out_get_buffer_size(const struct audio_stream *stream)
1927{
1928 struct stream_out *out = (struct stream_out *)stream;
1929
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001930 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001932 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1933 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001935 return out->config.period_size *
1936 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937}
1938
1939static uint32_t out_get_channels(const struct audio_stream *stream)
1940{
1941 struct stream_out *out = (struct stream_out *)stream;
1942
1943 return out->channel_mask;
1944}
1945
1946static audio_format_t out_get_format(const struct audio_stream *stream)
1947{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948 struct stream_out *out = (struct stream_out *)stream;
1949
1950 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951}
1952
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001953static int out_set_format(struct audio_stream *stream __unused,
1954 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955{
1956 return -ENOSYS;
1957}
1958
1959static int out_standby(struct audio_stream *stream)
1960{
1961 struct stream_out *out = (struct stream_out *)stream;
1962 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301964 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1965 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001966 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1967 /* Ignore standby in case of voip call because the voip output
1968 * stream is closed in adev_close_output_stream()
1969 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301970 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001971 return 0;
1972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001974 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001976 if (adev->adm_deregister_stream)
1977 adev->adm_deregister_stream(adev->adm_data, out->handle);
1978
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001979 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001981 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001982 if (out->pcm) {
1983 pcm_close(out->pcm);
1984 out->pcm = NULL;
1985 }
1986 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001987 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301989 out->send_next_track_params = false;
1990 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001991 out->gapless_mdata.encoder_delay = 0;
1992 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 if (out->compr != NULL) {
1994 compress_close(out->compr);
1995 out->compr = NULL;
1996 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001997 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001999 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 }
2001 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302002 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 return 0;
2004}
2005
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002006static int out_dump(const struct audio_stream *stream __unused,
2007 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008{
2009 return 0;
2010}
2011
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002012static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2013{
2014 int ret = 0;
2015 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002016
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002017 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002018 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002019 return -EINVAL;
2020 }
2021
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302022 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002023
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002024 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2025 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302026 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002027 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002028 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2029 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302030 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002031 }
2032
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002033 ALOGV("%s new encoder delay %u and padding %u", __func__,
2034 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2035
2036 return 0;
2037}
2038
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002039static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2040{
2041 return out == adev->primary_output || out == adev->voice_tx_output;
2042}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2045{
2046 struct stream_out *out = (struct stream_out *)stream;
2047 struct audio_device *adev = out->dev;
2048 struct str_parms *parms;
2049 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002050 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
sangwoobc677242013-08-08 16:53:43 +09002052 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002053 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302055 if (!parms)
2056 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002057 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2058 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002060 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002061 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302064 * When HDMI cable is unplugged/usb hs is disconnected the
2065 * music playback is paused and the policy manager sends routing=0
2066 * But the audioflingercontinues to write data until standby time
2067 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 * Avoid this by routing audio to speaker until standby.
2069 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302070 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2071 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002072 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002073 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2074 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075 }
2076
2077 /*
2078 * select_devices() call below switches all the usecases on the same
2079 * backend to the new device. Refer to check_usecases_codec_backend() in
2080 * the select_devices(). But how do we undo this?
2081 *
2082 * For example, music playback is active on headset (deep-buffer usecase)
2083 * and if we go to ringtones and select a ringtone, low-latency usecase
2084 * will be started on headset+speaker. As we can't enable headset+speaker
2085 * and headset devices at the same time, select_devices() switches the music
2086 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2087 * So when the ringtone playback is completed, how do we undo the same?
2088 *
2089 * We are relying on the out_set_parameters() call on deep-buffer output,
2090 * once the ringtone playback is ended.
2091 * NOTE: We should not check if the current devices are same as new devices.
2092 * Because select_devices() must be called to switch back the music
2093 * playback to headset.
2094 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002095 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002096 out->devices = val;
2097
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302098 if (!out->standby) {
2099 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2100 adev->perf_lock_opts,
2101 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002102 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302103 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2104 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002105
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002106 if (output_drives_call(adev, out)) {
2107 if(!voice_is_in_call(adev)) {
2108 if (adev->mode == AUDIO_MODE_IN_CALL) {
2109 adev->current_call_output = out;
2110 ret = voice_start_call(adev);
2111 }
2112 } else {
2113 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002114 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002115 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002116 }
2117 }
2118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002120 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002122
2123 if (out == adev->primary_output) {
2124 pthread_mutex_lock(&adev->lock);
2125 audio_extn_set_parameters(adev, parms);
2126 pthread_mutex_unlock(&adev->lock);
2127 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002128 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002129 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002130 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002131
2132 audio_extn_dts_create_state_notifier_node(out->usecase);
2133 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2134 popcount(out->channel_mask),
2135 out->playback_started);
2136
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002137 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002138 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302141error:
Eric Laurent994a6932013-07-17 11:51:42 -07002142 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 return ret;
2144}
2145
2146static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2147{
2148 struct stream_out *out = (struct stream_out *)stream;
2149 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002150 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 char value[256];
2152 struct str_parms *reply = str_parms_create();
2153 size_t i, j;
2154 int ret;
2155 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002156
2157 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002158 if (reply) {
2159 str_parms_destroy(reply);
2160 }
2161 if (query) {
2162 str_parms_destroy(query);
2163 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002164 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2165 return NULL;
2166 }
2167
Eric Laurent994a6932013-07-17 11:51:42 -07002168 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2170 if (ret >= 0) {
2171 value[0] = '\0';
2172 i = 0;
2173 while (out->supported_channel_masks[i] != 0) {
2174 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2175 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2176 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002177 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002179 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 first = false;
2181 break;
2182 }
2183 }
2184 i++;
2185 }
2186 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2187 str = str_parms_to_str(reply);
2188 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002189 voice_extn_out_get_parameters(out, query, reply);
2190 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002191 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002192 free(str);
2193 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002194 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002196
Alexy Joseph62142aa2015-11-16 15:10:34 -08002197
2198 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2199 if (ret >= 0) {
2200 value[0] = '\0';
2201 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2202 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302203 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002204 } else {
2205 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302206 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002207 }
2208 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002209 if (str)
2210 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002211 str = str_parms_to_str(reply);
2212 }
2213
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002214 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2215 if (ret >= 0) {
2216 value[0] = '\0';
2217 i = 0;
2218 first = true;
2219 while (out->supported_formats[i] != 0) {
2220 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2221 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2222 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002223 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002224 }
2225 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2226 first = false;
2227 break;
2228 }
2229 }
2230 i++;
2231 }
2232 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002233 if (str)
2234 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002235 str = str_parms_to_str(reply);
2236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 str_parms_destroy(query);
2238 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002239 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 return str;
2241}
2242
2243static uint32_t out_get_latency(const struct audio_stream_out *stream)
2244{
2245 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002246 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247
Alexy Josephaa54c872014-12-03 02:46:47 -08002248 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002249 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002250 } else {
2251 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002253 }
2254
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302255 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002256 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257}
2258
2259static int out_set_volume(struct audio_stream_out *stream, float left,
2260 float right)
2261{
Eric Laurenta9024de2013-04-04 09:19:12 -07002262 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263 int volume[2];
2264
Eric Laurenta9024de2013-04-04 09:19:12 -07002265 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2266 /* only take left channel into account: the API is for stereo anyway */
2267 out->muted = (left == 0.0f);
2268 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002269 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002270 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2271 /*
2272 * Set mute or umute on HDMI passthrough stream.
2273 * Only take left channel into account.
2274 * Mute is 0 and unmute 1
2275 */
2276 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2277 } else {
2278 char mixer_ctl_name[128];
2279 struct audio_device *adev = out->dev;
2280 struct mixer_ctl *ctl;
2281 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002282 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002283
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002284 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2285 "Compress Playback %d Volume", pcm_device_id);
2286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2287 if (!ctl) {
2288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2289 __func__, mixer_ctl_name);
2290 return -EINVAL;
2291 }
2292 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2293 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2294 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2295 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002297 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 return -ENOSYS;
2300}
2301
2302static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2303 size_t bytes)
2304{
2305 struct stream_out *out = (struct stream_out *)stream;
2306 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302307 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002308 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002310 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302311
Naresh Tanniru80659832014-06-04 18:17:56 +05302312 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002313
Ashish Jainbbce4322016-02-16 13:25:27 +05302314 if (is_offload_usecase(out->usecase)) {
2315 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302316 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2317 pthread_mutex_unlock(&out->lock);
2318 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302319 } else {
2320 /* increase written size during SSR to avoid mismatch
2321 * with the written frames count in AF
2322 */
2323 out->written += bytes / (out->config.channels * sizeof(short));
2324 ALOGD(" %s: sound card is not active/SSR state", __func__);
2325 ret= -EIO;
2326 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302327 }
2328 }
2329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002331 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002332 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002333 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2334 ret = voice_extn_compress_voip_start_output_stream(out);
2335 else
2336 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002337 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002340 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 goto exit;
2342 }
vivek mehta446c3962015-09-14 10:57:35 -07002343 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002344 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346
Ashish Jain81eb2a82015-05-13 10:52:34 +05302347 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002348 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302349 adev->is_channel_status_set = true;
2350 }
2351
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002352 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002353 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002354 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002355 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002356 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2357 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302358 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2359 ALOGD("copl(%p):send next track params in gapless", out);
2360 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2361 out->send_next_track_params = false;
2362 out->is_compr_metadata_avail = false;
2363 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002364 }
2365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302367 if (ret < 0)
2368 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302369 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002370 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302371 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302373 } else if (-ENETRESET == ret) {
2374 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2375 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2376 pthread_mutex_unlock(&out->lock);
2377 out_standby(&out->stream.common);
2378 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302380 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002382 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 out->playback_started = 1;
2384 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002385
2386 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2387 popcount(out->channel_mask),
2388 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 }
2390 pthread_mutex_unlock(&out->lock);
2391 return ret;
2392 } else {
2393 if (out->pcm) {
2394 if (out->muted)
2395 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002396
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302397 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002398
2399 if (adev->adm_request_focus)
2400 adev->adm_request_focus(adev->adm_data, out->handle);
2401
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002402 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2403 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2404 else
2405 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002406
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302407 if (ret < 0)
2408 ret = -errno;
2409 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002410 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002411
2412 if (adev->adm_abandon_focus)
2413 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 }
2416
2417exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302418 /* ToDo: There may be a corner case when SSR happens back to back during
2419 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302420 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302421 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302422 }
2423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424 pthread_mutex_unlock(&out->lock);
2425
2426 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002427 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002428 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302429 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302430 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302431 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302432 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302433 out->standby = true;
2434 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302436 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302437 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 }
2439 return bytes;
2440}
2441
2442static int out_get_render_position(const struct audio_stream_out *stream,
2443 uint32_t *dsp_frames)
2444{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302446 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002447
2448 if (dsp_frames == NULL)
2449 return -EINVAL;
2450
2451 *dsp_frames = 0;
2452 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002453 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002454 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302456 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302458 if (ret < 0)
2459 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002460 ALOGVV("%s rendered frames %d sample_rate %d",
2461 __func__, *dsp_frames, out->sample_rate);
2462 }
2463 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302464 if (-ENETRESET == ret) {
2465 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2466 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2467 return -EINVAL;
2468 } else if(ret < 0) {
2469 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2470 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302471 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2472 /*
2473 * Handle corner case where compress session is closed during SSR
2474 * and timestamp is queried
2475 */
2476 ALOGE(" ERROR: sound card not active, return error");
2477 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302478 } else {
2479 return 0;
2480 }
Zhou Song32a556e2015-05-05 10:46:56 +08002481 } else if (audio_is_linear_pcm(out->format)) {
2482 *dsp_frames = out->written;
2483 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 } else
2485 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486}
2487
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002488static int out_add_audio_effect(const struct audio_stream *stream __unused,
2489 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490{
2491 return 0;
2492}
2493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002494static int out_remove_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_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2501 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
2503 return -EINVAL;
2504}
2505
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002506static int out_get_presentation_position(const struct audio_stream_out *stream,
2507 uint64_t *frames, struct timespec *timestamp)
2508{
2509 struct stream_out *out = (struct stream_out *)stream;
2510 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002511 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002512
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002513 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002514
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002515 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002516 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302517 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002518 &out->sample_rate);
2519 ALOGVV("%s rendered frames %ld sample_rate %d",
2520 __func__, dsp_frames, out->sample_rate);
2521 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302522 if (ret < 0)
2523 ret = -errno;
2524 if (-ENETRESET == ret) {
2525 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2526 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2527 ret = -EINVAL;
2528 } else
2529 ret = 0;
2530
Eric Laurent949a0892013-09-20 09:20:13 -07002531 /* this is the best we can do */
2532 clock_gettime(CLOCK_MONOTONIC, timestamp);
2533 }
2534 } else {
2535 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002536 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002537 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2538 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002539 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002540 // This adjustment accounts for buffering after app processor.
2541 // It is based on estimated DSP latency per use case, rather than exact.
2542 signed_frames -=
2543 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2544
Eric Laurent949a0892013-09-20 09:20:13 -07002545 // It would be unusual for this value to be negative, but check just in case ...
2546 if (signed_frames >= 0) {
2547 *frames = signed_frames;
2548 ret = 0;
2549 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002550 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302551 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2552 *frames = out->written;
2553 clock_gettime(CLOCK_MONOTONIC, timestamp);
2554 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002555 }
2556 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002557 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002558 return ret;
2559}
2560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002561static int out_set_callback(struct audio_stream_out *stream,
2562 stream_callback_t callback, void *cookie)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565
2566 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002567 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002568 out->offload_callback = callback;
2569 out->offload_cookie = cookie;
2570 pthread_mutex_unlock(&out->lock);
2571 return 0;
2572}
2573
2574static int out_pause(struct audio_stream_out* stream)
2575{
2576 struct stream_out *out = (struct stream_out *)stream;
2577 int status = -ENOSYS;
2578 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002579 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002580 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002581 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302583 struct audio_device *adev = out->dev;
2584 int snd_scard_state = get_snd_card_state(adev);
2585
2586 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2587 status = compress_pause(out->compr);
2588
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002590
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302591 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002592 audio_extn_dts_notify_playback_state(out->usecase, 0,
2593 out->sample_rate, popcount(out->channel_mask),
2594 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 }
2596 pthread_mutex_unlock(&out->lock);
2597 }
2598 return status;
2599}
2600
2601static int out_resume(struct audio_stream_out* stream)
2602{
2603 struct stream_out *out = (struct stream_out *)stream;
2604 int status = -ENOSYS;
2605 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002606 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002607 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002609 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002610 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302611 struct audio_device *adev = out->dev;
2612 int snd_scard_state = get_snd_card_state(adev);
2613
2614 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2615 status = compress_resume(out->compr);
2616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002618
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302619 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002620 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2621 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 }
2623 pthread_mutex_unlock(&out->lock);
2624 }
2625 return status;
2626}
2627
2628static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2629{
2630 struct stream_out *out = (struct stream_out *)stream;
2631 int status = -ENOSYS;
2632 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002633 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002634 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002635 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2636 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2637 else
2638 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2639 pthread_mutex_unlock(&out->lock);
2640 }
2641 return status;
2642}
2643
2644static int out_flush(struct audio_stream_out* stream)
2645{
2646 struct stream_out *out = (struct stream_out *)stream;
2647 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002648 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002649 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002650 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002651 stop_compressed_output_l(out);
2652 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002653 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002654 return 0;
2655 }
2656 return -ENOSYS;
2657}
2658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659/** audio_stream_in implementation **/
2660static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2661{
2662 struct stream_in *in = (struct stream_in *)stream;
2663
2664 return in->config.rate;
2665}
2666
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002667static int in_set_sample_rate(struct audio_stream *stream __unused,
2668 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669{
2670 return -ENOSYS;
2671}
2672
2673static size_t in_get_buffer_size(const struct audio_stream *stream)
2674{
2675 struct stream_in *in = (struct stream_in *)stream;
2676
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002677 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2678 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002679 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2680 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002681
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002682 return in->config.period_size *
2683 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684}
2685
2686static uint32_t in_get_channels(const struct audio_stream *stream)
2687{
2688 struct stream_in *in = (struct stream_in *)stream;
2689
2690 return in->channel_mask;
2691}
2692
2693static audio_format_t in_get_format(const struct audio_stream *stream)
2694{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002695 struct stream_in *in = (struct stream_in *)stream;
2696
2697 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698}
2699
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002700static int in_set_format(struct audio_stream *stream __unused,
2701 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702{
2703 return -ENOSYS;
2704}
2705
2706static int in_standby(struct audio_stream *stream)
2707{
2708 struct stream_in *in = (struct stream_in *)stream;
2709 struct audio_device *adev = in->dev;
2710 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302711 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2712 stream, in->usecase, use_case_table[in->usecase]);
2713
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002714 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2715 /* Ignore standby in case of voip call because the voip input
2716 * stream is closed in adev_close_input_stream()
2717 */
2718 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2719 return status;
2720 }
2721
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002722 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002723 if (!in->standby && in->is_st_session) {
2724 ALOGD("%s: sound trigger pcm stop lab", __func__);
2725 audio_extn_sound_trigger_stop_lab(in);
2726 in->standby = 1;
2727 }
2728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002730 if (adev->adm_deregister_stream)
2731 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2732
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002733 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002735 if (in->pcm) {
2736 pcm_close(in->pcm);
2737 in->pcm = NULL;
2738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002740 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 }
2742 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002743 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 return status;
2745}
2746
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002747static int in_dump(const struct audio_stream *stream __unused,
2748 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749{
2750 return 0;
2751}
2752
2753static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2754{
2755 struct stream_in *in = (struct stream_in *)stream;
2756 struct audio_device *adev = in->dev;
2757 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002759 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302761 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 parms = str_parms_create_str(kvpairs);
2763
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302764 if (!parms)
2765 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002766 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002767 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002768
2769 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2770 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 val = atoi(value);
2772 /* no audio source uses val == 0 */
2773 if ((in->source != val) && (val != 0)) {
2774 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002775 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2776 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2777 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002778 (in->config.rate == 8000 || in->config.rate == 16000 ||
2779 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002780 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002781 err = voice_extn_compress_voip_open_input_stream(in);
2782 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002783 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002784 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002785 }
2786 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 }
2788 }
2789
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002790 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2791 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002793 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 in->device = val;
2795 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002796 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002797 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 }
2799 }
2800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002802 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803
2804 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302805error:
Eric Laurent994a6932013-07-17 11:51:42 -07002806 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 return ret;
2808}
2809
2810static char* in_get_parameters(const struct audio_stream *stream,
2811 const char *keys)
2812{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002813 struct stream_in *in = (struct stream_in *)stream;
2814 struct str_parms *query = str_parms_create_str(keys);
2815 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002816 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002817
2818 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002819 if (reply) {
2820 str_parms_destroy(reply);
2821 }
2822 if (query) {
2823 str_parms_destroy(query);
2824 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002825 ALOGE("in_get_parameters: failed to create query or reply");
2826 return NULL;
2827 }
2828
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002829 ALOGV("%s: enter: keys - %s", __func__, keys);
2830
2831 voice_extn_in_get_parameters(in, query, reply);
2832
2833 str = str_parms_to_str(reply);
2834 str_parms_destroy(query);
2835 str_parms_destroy(reply);
2836
2837 ALOGV("%s: exit: returns - %s", __func__, str);
2838 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839}
2840
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002841static int in_set_gain(struct audio_stream_in *stream __unused,
2842 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843{
2844 return 0;
2845}
2846
2847static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2848 size_t bytes)
2849{
2850 struct stream_in *in = (struct stream_in *)stream;
2851 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302852 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302853 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002855 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302856
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002857 if (in->is_st_session) {
2858 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2859 /* Read from sound trigger HAL */
2860 audio_extn_sound_trigger_read(in, buffer, bytes);
2861 pthread_mutex_unlock(&in->lock);
2862 return bytes;
2863 }
2864
Ashish Jainbbce4322016-02-16 13:25:27 +05302865 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002866 ALOGD(" %s: sound card is not active/SSR state", __func__);
2867 ret= -EIO;;
2868 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302869 }
2870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002872 pthread_mutex_lock(&adev->lock);
2873 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2874 ret = voice_extn_compress_voip_start_input_stream(in);
2875 else
2876 ret = start_input_stream(in);
2877 pthread_mutex_unlock(&adev->lock);
2878 if (ret != 0) {
2879 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 }
2881 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002882 if (adev->adm_register_input_stream)
2883 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002886 if (adev->adm_request_focus)
2887 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002890 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002891 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002892 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2893 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002894 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2895 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002896 else
2897 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302898 if (ret < 0)
2899 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 }
2901
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002902 if (adev->adm_abandon_focus)
2903 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 /*
2906 * Instead of writing zeroes here, we could trust the hardware
2907 * to always provide zeroes when muted.
2908 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302909 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2910 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 memset(buffer, 0, bytes);
2912
2913exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302914 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302915 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002916 if (-ENETRESET == ret)
2917 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 pthread_mutex_unlock(&in->lock);
2920
2921 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302922 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302923 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302924 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302925 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302926 in->standby = true;
2927 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302928 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002930 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05302931 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302932 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002933 }
2934 return bytes;
2935}
2936
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002937static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938{
2939 return 0;
2940}
2941
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002942static int add_remove_audio_effect(const struct audio_stream *stream,
2943 effect_handle_t effect,
2944 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002946 struct stream_in *in = (struct stream_in *)stream;
2947 int status = 0;
2948 effect_descriptor_t desc;
2949
2950 status = (*effect)->get_descriptor(effect, &desc);
2951 if (status != 0)
2952 return status;
2953
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002954 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002955 pthread_mutex_lock(&in->dev->lock);
2956 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2957 in->enable_aec != enable &&
2958 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2959 in->enable_aec = enable;
2960 if (!in->standby)
2961 select_devices(in->dev, in->usecase);
2962 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002963 if (in->enable_ns != enable &&
2964 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2965 in->enable_ns = enable;
2966 if (!in->standby)
2967 select_devices(in->dev, in->usecase);
2968 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002969 pthread_mutex_unlock(&in->dev->lock);
2970 pthread_mutex_unlock(&in->lock);
2971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 return 0;
2973}
2974
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002975static int in_add_audio_effect(const struct audio_stream *stream,
2976 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977{
Eric Laurent994a6932013-07-17 11:51:42 -07002978 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002979 return add_remove_audio_effect(stream, effect, true);
2980}
2981
2982static int in_remove_audio_effect(const struct audio_stream *stream,
2983 effect_handle_t effect)
2984{
Eric Laurent994a6932013-07-17 11:51:42 -07002985 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002986 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987}
2988
2989static int adev_open_output_stream(struct audio_hw_device *dev,
2990 audio_io_handle_t handle,
2991 audio_devices_t devices,
2992 audio_output_flags_t flags,
2993 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002994 struct audio_stream_out **stream_out,
2995 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996{
2997 struct audio_device *adev = (struct audio_device *)dev;
2998 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302999 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003000 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303003
3004 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3005 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003006 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303007 return -EINVAL;
3008 }
3009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3011
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303012 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3013 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3014 devices, flags, &out->stream);
3015
3016
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003017 if (!out) {
3018 return -ENOMEM;
3019 }
3020
Haynes Mathew George204045b2015-02-25 20:32:03 -08003021 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003022 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003023 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 if (devices == AUDIO_DEVICE_NONE)
3026 devices = AUDIO_DEVICE_OUT_SPEAKER;
3027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 out->flags = flags;
3029 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003030 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003031 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003032 out->sample_rate = config->sample_rate;
3033 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3034 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003035 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003036 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003037 out->non_blocking = 0;
3038 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039
3040 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003041 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303042 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3043 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003044 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3045 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3046
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003047 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003048 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3049 ret = read_hdmi_channel_masks(out);
3050
3051 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3052 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003053 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003054 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003055 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003056
3057 if (config->sample_rate == 0)
3058 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3059 if (config->channel_mask == 0)
3060 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3061
3062 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3065 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003067 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003069 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3070 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003071 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003072 ret = voice_extn_compress_voip_open_output_stream(out);
3073 if (ret != 0) {
3074 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3075 __func__, ret);
3076 goto error_open;
3077 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003078 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3079 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3080
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3082 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3083 ALOGE("%s: Unsupported Offload information", __func__);
3084 ret = -EINVAL;
3085 goto error_open;
3086 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003087
3088 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3089 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3090 ALOGV("read and update_pass through formats");
3091 ret = audio_extn_dolby_update_passt_formats(adev, out);
3092 if(ret != 0) {
3093 goto error_open;
3094 }
3095 if(config->offload_info.format == 0)
3096 config->offload_info.format = out->supported_formats[0];
3097 }
3098
Mingming Yin90310102013-11-13 16:57:00 -08003099 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003100 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003101 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 ret = -EINVAL;
3103 goto error_open;
3104 }
3105
3106 out->compr_config.codec = (struct snd_codec *)
3107 calloc(1, sizeof(struct snd_codec));
3108
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003109 if (!out->compr_config.codec) {
3110 ret = -ENOMEM;
3111 goto error_open;
3112 }
3113
vivek mehta0ea887a2015-08-26 14:01:20 -07003114 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003115 out->usecase = get_offload_usecase(adev, true);
3116 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003117 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003118 out->stream.set_callback = out_set_callback;
3119 out->stream.pause = out_pause;
3120 out->stream.resume = out_resume;
3121 out->stream.drain = out_drain;
3122 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003123 out->usecase = get_offload_usecase(adev, false);
3124 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003125 }
vivek mehta446c3962015-09-14 10:57:35 -07003126
3127 if (out->usecase == USECASE_INVALID) {
Alexy Josephb1379942016-01-29 15:49:38 -08003128 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
vivek mehta446c3962015-09-14 10:57:35 -07003129 ret = -EEXIST;
3130 goto error_open;
3131 }
3132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133 if (config->offload_info.channel_mask)
3134 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003135 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003137 config->offload_info.channel_mask = config->channel_mask;
3138 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003139 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 out->sample_rate = config->offload_info.sample_rate;
3141
Mingming Yin3ee55c62014-08-04 14:23:35 -07003142 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003144 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003145 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003146 audio_extn_dolby_get_snd_codec_id(adev, out,
3147 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003148 else
3149 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003151
3152 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3153 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003154 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003155 platform_get_pcm_offload_buffer_size(&config->offload_info);
3156 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3157 out->compr_config.fragment_size =
3158 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003159 } else {
3160 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003161 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003162 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3164 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003165 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003166 out->compr_config.codec->bit_rate =
3167 config->offload_info.bit_rate;
3168 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003169 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303171 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003172 /*TODO: Do we need to change it for passthrough */
3173 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174
Manish Dewangana6fc5442015-08-24 20:30:31 +05303175 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3176 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3177 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3178 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003179 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3180 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003181 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003182 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003183 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3184 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003185
Mingming Yin3ee55c62014-08-04 14:23:35 -07003186 if (out->bit_width == 24) {
3187 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3188 }
3189
Amit Shekhar6f461b12014-08-01 14:52:58 -07003190 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303191 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003192
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3194 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003195
Mingming Yin497419f2015-07-01 16:57:32 -07003196 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003197 //this flag is set from framework only if its for PCM formats
3198 //no need to check for PCM format again
3199 out->non_blocking = 0;
3200 out->use_small_bufs = true;
3201 ALOGI("Keep write blocking for small buff: non_blockling %d",
3202 out->non_blocking);
3203 }
3204
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003205 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303206 out->send_next_track_params = false;
3207 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003208 out->offload_state = OFFLOAD_STATE_IDLE;
3209 out->playback_started = 0;
3210
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003211 audio_extn_dts_create_state_notifier_node(out->usecase);
3212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 create_offload_callback_thread(out);
3214 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3215 __func__, config->offload_info.version,
3216 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003217 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003218 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003219 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303220 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003221 if (ret != 0) {
3222 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3223 __func__, ret);
3224 goto error_open;
3225 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003226 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3227 if (config->sample_rate == 0)
3228 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3229 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3230 config->sample_rate != 8000) {
3231 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3232 ret = -EINVAL;
3233 goto error_open;
3234 }
3235 out->sample_rate = config->sample_rate;
3236 out->config.rate = config->sample_rate;
3237 if (config->format == AUDIO_FORMAT_DEFAULT)
3238 config->format = AUDIO_FORMAT_PCM_16_BIT;
3239 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3240 config->format = AUDIO_FORMAT_PCM_16_BIT;
3241 ret = -EINVAL;
3242 goto error_open;
3243 }
3244 out->format = config->format;
3245 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3246 out->config = pcm_config_afe_proxy_playback;
3247 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003248 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3249 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3250 out->config = pcm_config_low_latency;
3251 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003252 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003253 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3255 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003257 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3258 format = AUDIO_FORMAT_PCM_16_BIT;
3259 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3260 out->config = pcm_config_deep_buffer;
3261 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003262 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003263 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003264 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003265 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003266 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003267 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 }
3269
Amit Shekhar1d896042014-10-03 13:16:09 -07003270 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3271 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003272 /* TODO remove this hardcoding and check why width is zero*/
3273 if (out->bit_width == 0)
3274 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003275 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3276 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003277 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303278 out->bit_width, out->channel_mask,
3279 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003280 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3281 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3282 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003283 if(adev->primary_output == NULL)
3284 adev->primary_output = out;
3285 else {
3286 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003287 ret = -EEXIST;
3288 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003289 }
3290 }
3291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 /* Check if this usecase is already existing */
3293 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003294 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3295 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003298 ret = -EEXIST;
3299 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 }
3301 pthread_mutex_unlock(&adev->lock);
3302
3303 out->stream.common.get_sample_rate = out_get_sample_rate;
3304 out->stream.common.set_sample_rate = out_set_sample_rate;
3305 out->stream.common.get_buffer_size = out_get_buffer_size;
3306 out->stream.common.get_channels = out_get_channels;
3307 out->stream.common.get_format = out_get_format;
3308 out->stream.common.set_format = out_set_format;
3309 out->stream.common.standby = out_standby;
3310 out->stream.common.dump = out_dump;
3311 out->stream.common.set_parameters = out_set_parameters;
3312 out->stream.common.get_parameters = out_get_parameters;
3313 out->stream.common.add_audio_effect = out_add_audio_effect;
3314 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3315 out->stream.get_latency = out_get_latency;
3316 out->stream.set_volume = out_set_volume;
3317 out->stream.write = out_write;
3318 out->stream.get_render_position = out_get_render_position;
3319 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003320 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003323 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003324 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
3326 config->format = out->stream.common.get_format(&out->stream.common);
3327 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3328 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3329
3330 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303331 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003332 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003333
3334 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3335 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3336 popcount(out->channel_mask), out->playback_started);
3337
Eric Laurent994a6932013-07-17 11:51:42 -07003338 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003340
3341error_open:
3342 free(out);
3343 *stream_out = NULL;
3344 ALOGD("%s: exit: ret %d", __func__, ret);
3345 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346}
3347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003348static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 struct audio_stream_out *stream)
3350{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 struct stream_out *out = (struct stream_out *)stream;
3352 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003353 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303355 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3356
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003357 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303358 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003359 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303360 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003361 if(ret != 0)
3362 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3363 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003364 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003365 out_standby(&stream->common);
3366
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003367 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003368 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003369 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003370 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003371 if (out->compr_config.codec != NULL)
3372 free(out->compr_config.codec);
3373 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003374
3375 if (adev->voice_tx_output == out)
3376 adev->voice_tx_output = NULL;
3377
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 pthread_cond_destroy(&out->cond);
3379 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003381 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382}
3383
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003384static void close_compress_sessions(struct audio_device *adev)
3385{
Mingming Yin7b762e72015-03-04 13:47:32 -08003386 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303387 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003388 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003389 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303390
3391 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003392 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303393 if (is_offload_usecase(usecase->id)) {
3394 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003395 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3396 out = usecase->stream.out;
3397 pthread_mutex_unlock(&adev->lock);
3398 out_standby(&out->stream.common);
3399 pthread_mutex_lock(&adev->lock);
3400 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303401 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003402 }
3403 pthread_mutex_unlock(&adev->lock);
3404}
3405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3407{
3408 struct audio_device *adev = (struct audio_device *)dev;
3409 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003411 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003412 int ret;
3413 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003415 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303418 if (!parms)
3419 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003420 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3421 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303422 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303423 if (strstr(snd_card_status, "OFFLINE")) {
3424 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303425 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003426 //close compress sessions on OFFLINE status
3427 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303428 } else if (strstr(snd_card_status, "ONLINE")) {
3429 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303430 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003431 //send dts hpx license if enabled
3432 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303433 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303434 }
3435
3436 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003437 status = voice_set_parameters(adev, parms);
3438 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003439 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003441 status = platform_set_parameters(adev->platform, parms);
3442 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003443 goto done;
3444
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003445 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3446 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003447 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3449 adev->bluetooth_nrec = true;
3450 else
3451 adev->bluetooth_nrec = false;
3452 }
3453
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003454 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3455 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3457 adev->screen_off = false;
3458 else
3459 adev->screen_off = true;
3460 }
3461
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003462 ret = str_parms_get_int(parms, "rotation", &val);
3463 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003464 bool reverse_speakers = false;
3465 switch(val) {
3466 // FIXME: note that the code below assumes that the speakers are in the correct placement
3467 // relative to the user when the device is rotated 90deg from its default rotation. This
3468 // assumption is device-specific, not platform-specific like this code.
3469 case 270:
3470 reverse_speakers = true;
3471 break;
3472 case 0:
3473 case 90:
3474 case 180:
3475 break;
3476 default:
3477 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003478 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003479 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003480 if (status == 0) {
3481 if (adev->speaker_lr_swap != reverse_speakers) {
3482 adev->speaker_lr_swap = reverse_speakers;
3483 // only update the selected device if there is active pcm playback
3484 struct audio_usecase *usecase;
3485 struct listnode *node;
3486 list_for_each(node, &adev->usecase_list) {
3487 usecase = node_to_item(node, struct audio_usecase, list);
3488 if (usecase->type == PCM_PLAYBACK) {
3489 select_devices(adev, usecase->id);
3490 break;
3491 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003492 }
3493 }
3494 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003495 }
3496
Mingming Yin514a8bc2014-07-29 15:22:21 -07003497 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3498 if (ret >= 0) {
3499 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3500 adev->bt_wb_speech_enabled = true;
3501 else
3502 adev->bt_wb_speech_enabled = false;
3503 }
3504
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003505 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3506 if (ret >= 0) {
3507 val = atoi(value);
3508 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3509 ALOGV("cache new edid");
3510 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003511 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3512 /*
3513 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3514 * Per AudioPolicyManager, USB device is higher priority than WFD.
3515 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3516 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3517 * starting voice call on USB
3518 */
3519 ALOGV("detected USB connect .. disable proxy");
3520 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003521 }
3522 }
3523
3524 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3525 if (ret >= 0) {
3526 val = atoi(value);
3527 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3528 ALOGV("invalidate cached edid");
3529 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003530 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3531 ALOGV("detected USB disconnect .. enable proxy");
3532 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003533 }
3534 }
3535
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003536 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003537
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003538done:
3539 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003540 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303541error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003542 ALOGV("%s: exit with code(%d)", __func__, status);
3543 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544}
3545
3546static char* adev_get_parameters(const struct audio_hw_device *dev,
3547 const char *keys)
3548{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003549 struct audio_device *adev = (struct audio_device *)dev;
3550 struct str_parms *reply = str_parms_create();
3551 struct str_parms *query = str_parms_create_str(keys);
3552 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303553 char value[256] = {0};
3554 int ret = 0;
3555
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003556 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003557 if (reply) {
3558 str_parms_destroy(reply);
3559 }
3560 if (query) {
3561 str_parms_destroy(query);
3562 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003563 ALOGE("adev_get_parameters: failed to create query or reply");
3564 return NULL;
3565 }
3566
Naresh Tannirud7205b62014-06-20 02:54:48 +05303567 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3568 sizeof(value));
3569 if (ret >=0) {
3570 int val = 1;
3571 pthread_mutex_lock(&adev->snd_card_status.lock);
3572 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3573 val = 0;
3574 pthread_mutex_unlock(&adev->snd_card_status.lock);
3575 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3576 goto exit;
3577 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003578
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003579 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003580 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003581 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003582 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303583 pthread_mutex_unlock(&adev->lock);
3584
Naresh Tannirud7205b62014-06-20 02:54:48 +05303585exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003586 str = str_parms_to_str(reply);
3587 str_parms_destroy(query);
3588 str_parms_destroy(reply);
3589
3590 ALOGV("%s: exit: returns - %s", __func__, str);
3591 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592}
3593
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003594static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595{
3596 return 0;
3597}
3598
3599static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3600{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003601 int ret;
3602 struct audio_device *adev = (struct audio_device *)dev;
3603 pthread_mutex_lock(&adev->lock);
3604 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003605 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003606 pthread_mutex_unlock(&adev->lock);
3607 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608}
3609
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003610static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3611 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612{
3613 return -ENOSYS;
3614}
3615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003616static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3617 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618{
3619 return -ENOSYS;
3620}
3621
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003622static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3623 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624{
3625 return -ENOSYS;
3626}
3627
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003628static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3629 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630{
3631 return -ENOSYS;
3632}
3633
3634static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3635{
3636 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638 pthread_mutex_lock(&adev->lock);
3639 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003640 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003642 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003643 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003644 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003645 adev->current_call_output = NULL;
3646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648 pthread_mutex_unlock(&adev->lock);
3649 return 0;
3650}
3651
3652static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3653{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003654 int ret;
3655
3656 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003657 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003658 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3659 pthread_mutex_unlock(&adev->lock);
3660
3661 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662}
3663
3664static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3665{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003666 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 return 0;
3668}
3669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003670static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 const struct audio_config *config)
3672{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003673 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003675 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3676 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677}
3678
3679static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003680 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 audio_devices_t devices,
3682 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003683 struct audio_stream_in **stream_in,
3684 audio_input_flags_t flags __unused,
3685 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003686 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687{
3688 struct audio_device *adev = (struct audio_device *)dev;
3689 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003690 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003691 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003692 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 *stream_in = NULL;
3695 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3696 return -EINVAL;
3697
3698 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003699
3700 if (!in) {
3701 ALOGE("failed to allocate input stream");
3702 return -ENOMEM;
3703 }
3704
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303705 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003706 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3707 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003709 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003710 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 in->stream.common.get_sample_rate = in_get_sample_rate;
3713 in->stream.common.set_sample_rate = in_set_sample_rate;
3714 in->stream.common.get_buffer_size = in_get_buffer_size;
3715 in->stream.common.get_channels = in_get_channels;
3716 in->stream.common.get_format = in_get_format;
3717 in->stream.common.set_format = in_set_format;
3718 in->stream.common.standby = in_standby;
3719 in->stream.common.dump = in_dump;
3720 in->stream.common.set_parameters = in_set_parameters;
3721 in->stream.common.get_parameters = in_get_parameters;
3722 in->stream.common.add_audio_effect = in_add_audio_effect;
3723 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3724 in->stream.set_gain = in_set_gain;
3725 in->stream.read = in_read;
3726 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3727
3728 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003729 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 in->standby = 1;
3732 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003733 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003734 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735
3736 /* Update config params with the requested sample rate and channels */
3737 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003738 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3739 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3740 is_low_latency = true;
3741#if LOW_LATENCY_CAPTURE_USE_CASE
3742 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3743#endif
3744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003747 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003749 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303750 if (adev->mode != AUDIO_MODE_IN_CALL) {
3751 ret = -EINVAL;
3752 goto err_open;
3753 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003754 if (config->sample_rate == 0)
3755 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3756 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3757 config->sample_rate != 8000) {
3758 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3759 ret = -EINVAL;
3760 goto err_open;
3761 }
3762 if (config->format == AUDIO_FORMAT_DEFAULT)
3763 config->format = AUDIO_FORMAT_PCM_16_BIT;
3764 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3765 config->format = AUDIO_FORMAT_PCM_16_BIT;
3766 ret = -EINVAL;
3767 goto err_open;
3768 }
3769
3770 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3771 in->config = pcm_config_afe_proxy_record;
3772 in->config.channels = channel_count;
3773 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303774 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3775 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003776 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003777 audio_extn_compr_cap_format_supported(config->format) &&
3778 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003779 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003780 } else {
3781 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003782 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003783 buffer_size = get_input_buffer_size(config->sample_rate,
3784 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003785 channel_count,
3786 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003787 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003788 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3789 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3790 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003791 (in->config.rate == 8000 || in->config.rate == 16000 ||
3792 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003793 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3794 voice_extn_compress_voip_open_input_stream(in);
3795 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003796 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003798 /* This stream could be for sound trigger lab,
3799 get sound trigger pcm if present */
3800 audio_extn_sound_trigger_check_and_get_session(in);
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003803 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003804 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
3806err_open:
3807 free(in);
3808 *stream_in = NULL;
3809 return ret;
3810}
3811
3812static void adev_close_input_stream(struct audio_hw_device *dev,
3813 struct audio_stream_in *stream)
3814{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003815 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003816 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003817 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303818
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303819 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003820
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303821 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003822 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303823
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003824 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303825 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003826 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303827 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003828 if (ret != 0)
3829 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3830 __func__, ret);
3831 } else
3832 in_standby(&stream->common);
3833
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003834 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003835 audio_extn_ssr_deinit();
3836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837
Mingming Yine62d7842013-10-25 16:26:03 -07003838 if(audio_extn_compr_cap_enabled() &&
3839 audio_extn_compr_cap_format_supported(in->config.format))
3840 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003841
Mingming Yinfd7607b2016-01-22 12:48:44 -08003842 if (in->is_st_session) {
3843 ALOGV("%s: sound trigger pcm stop lab", __func__);
3844 audio_extn_sound_trigger_stop_lab(in);
3845 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003846 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003847 return;
3848}
3849
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003850static int adev_dump(const audio_hw_device_t *device __unused,
3851 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852{
3853 return 0;
3854}
3855
3856static int adev_close(hw_device_t *device)
3857{
3858 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003859
3860 if (!adev)
3861 return 0;
3862
3863 pthread_mutex_lock(&adev_init_lock);
3864
3865 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003866 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003867 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003868 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003869 audio_route_free(adev->audio_route);
3870 free(adev->snd_dev_ref_cnt);
3871 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003872 if (adev->adm_deinit)
3873 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003874 free(device);
3875 adev = NULL;
3876 }
3877 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 return 0;
3880}
3881
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003882/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3883 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3884 * just that it _might_ work.
3885 */
3886static int period_size_is_plausible_for_low_latency(int period_size)
3887{
3888 switch (period_size) {
3889 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003890 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003891 case 240:
3892 case 320:
3893 case 480:
3894 return 1;
3895 default:
3896 return 0;
3897 }
3898}
3899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900static int adev_open(const hw_module_t *module, const char *name,
3901 hw_device_t **device)
3902{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003903 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3905
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003906 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003907 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003908 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003909 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003910 ALOGD("%s: returning existing instance of adev", __func__);
3911 ALOGD("%s: exit", __func__);
3912 pthread_mutex_unlock(&adev_init_lock);
3913 return 0;
3914 }
3915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916 adev = calloc(1, sizeof(struct audio_device));
3917
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003918 if (!adev) {
3919 pthread_mutex_unlock(&adev_init_lock);
3920 return -ENOMEM;
3921 }
3922
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003923 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3926 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3927 adev->device.common.module = (struct hw_module_t *)module;
3928 adev->device.common.close = adev_close;
3929
3930 adev->device.init_check = adev_init_check;
3931 adev->device.set_voice_volume = adev_set_voice_volume;
3932 adev->device.set_master_volume = adev_set_master_volume;
3933 adev->device.get_master_volume = adev_get_master_volume;
3934 adev->device.set_master_mute = adev_set_master_mute;
3935 adev->device.get_master_mute = adev_get_master_mute;
3936 adev->device.set_mode = adev_set_mode;
3937 adev->device.set_mic_mute = adev_set_mic_mute;
3938 adev->device.get_mic_mute = adev_get_mic_mute;
3939 adev->device.set_parameters = adev_set_parameters;
3940 adev->device.get_parameters = adev_get_parameters;
3941 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3942 adev->device.open_output_stream = adev_open_output_stream;
3943 adev->device.close_output_stream = adev_close_output_stream;
3944 adev->device.open_input_stream = adev_open_input_stream;
3945 adev->device.close_input_stream = adev_close_input_stream;
3946 adev->device.dump = adev_dump;
3947
3948 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003950 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003951 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003954 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07003955 adev->allow_afe_proxy_usage = true;
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};