blob: dff662a62bcdd89543b0cf145b84217c7b34ce29 [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),
Mingming Yin3a941d42016-02-17 18:08:05 -0800234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800247 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
248 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
249};
250
251//list of all supported sample rates by HDMI specification.
252static const int out_hdmi_sample_rates[] = {
253 32000, 44100, 48000, 88200, 96000, 176400, 192000,
254};
255
256static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
257 STRING_TO_ENUM(32000),
258 STRING_TO_ENUM(44100),
259 STRING_TO_ENUM(48000),
260 STRING_TO_ENUM(88200),
261 STRING_TO_ENUM(96000),
262 STRING_TO_ENUM(176400),
263 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700264};
265
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700266static struct audio_device *adev = NULL;
267static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700268static unsigned int audio_device_ref_count;
269
vivek mehtaa76401a2015-04-24 14:12:15 -0700270__attribute__ ((visibility ("default")))
271bool audio_hw_send_gain_dep_calibration(int level) {
272 bool ret_val = false;
273 ALOGV("%s: called ... ", __func__);
274
275 pthread_mutex_lock(&adev_init_lock);
276
277 if (adev != NULL && adev->platform != NULL) {
278 pthread_mutex_lock(&adev->lock);
279 ret_val = platform_send_gain_dep_cal(adev->platform, level);
280 pthread_mutex_unlock(&adev->lock);
281 } else {
282 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
283 }
284
285 pthread_mutex_unlock(&adev_init_lock);
286
287 return ret_val;
288}
289
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800290static int check_and_set_gapless_mode(struct audio_device *adev) {
291
292
293 char value[PROPERTY_VALUE_MAX] = {0};
294 bool gapless_enabled = false;
295 const char *mixer_ctl_name = "Compress Gapless Playback";
296 struct mixer_ctl *ctl;
297
298 ALOGV("%s:", __func__);
299 property_get("audio.offload.gapless.enabled", value, NULL);
300 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
301
302 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
303 if (!ctl) {
304 ALOGE("%s: Could not get ctl for mixer cmd - %s",
305 __func__, mixer_ctl_name);
306 return -EINVAL;
307 }
308
309 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
310 ALOGE("%s: Could not set gapless mode %d",
311 __func__, gapless_enabled);
312 return -EINVAL;
313 }
314 return 0;
315}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700317static bool is_supported_format(audio_format_t format)
318{
Eric Laurent86e17132013-09-12 17:49:30 -0700319 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530320 format == AUDIO_FORMAT_AAC_LC ||
321 format == AUDIO_FORMAT_AAC_HE_V1 ||
322 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530323 format == AUDIO_FORMAT_AAC_ADTS_LC ||
324 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
325 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800326 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700327 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700328 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800329 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530330 format == AUDIO_FORMAT_ALAC ||
331 format == AUDIO_FORMAT_APE ||
332 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800333 format == AUDIO_FORMAT_WMA ||
334 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800335 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700336
337 return false;
338}
339
340static int get_snd_codec_id(audio_format_t format)
341{
342 int id = 0;
343
Ashish Jainf9b78162014-08-25 20:36:25 +0530344 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700345 case AUDIO_FORMAT_MP3:
346 id = SND_AUDIOCODEC_MP3;
347 break;
348 case AUDIO_FORMAT_AAC:
349 id = SND_AUDIOCODEC_AAC;
350 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530351 case AUDIO_FORMAT_AAC_ADTS:
352 id = SND_AUDIOCODEC_AAC;
353 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530354 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700355 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800356 id = SND_AUDIOCODEC_PCM;
357 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700358 case AUDIO_FORMAT_FLAC:
359 id = SND_AUDIOCODEC_FLAC;
360 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530361 case AUDIO_FORMAT_ALAC:
362 id = SND_AUDIOCODEC_ALAC;
363 break;
364 case AUDIO_FORMAT_APE:
365 id = SND_AUDIOCODEC_APE;
366 break;
367 case AUDIO_FORMAT_VORBIS:
368 id = SND_AUDIOCODEC_VORBIS;
369 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800370 case AUDIO_FORMAT_WMA:
371 id = SND_AUDIOCODEC_WMA;
372 break;
373 case AUDIO_FORMAT_WMA_PRO:
374 id = SND_AUDIOCODEC_WMA_PRO;
375 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700376 default:
Mingming Yin90310102013-11-13 16:57:00 -0800377 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700378 }
379
380 return id;
381}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800382
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530383int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530384{
385 int snd_scard_state;
386
387 if (!adev)
388 return SND_CARD_STATE_OFFLINE;
389
390 pthread_mutex_lock(&adev->snd_card_status.lock);
391 snd_scard_state = adev->snd_card_status.state;
392 pthread_mutex_unlock(&adev->snd_card_status.lock);
393
394 return snd_scard_state;
395}
396
397static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
398{
399 if (!adev)
400 return -ENOSYS;
401
402 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700403 if (adev->snd_card_status.state != snd_scard_state) {
404 adev->snd_card_status.state = snd_scard_state;
405 platform_snd_card_update(adev->platform, snd_scard_state);
406 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530407 pthread_mutex_unlock(&adev->snd_card_status.lock);
408
409 return 0;
410}
411
Avinash Vaish71a8b972014-07-24 15:36:33 +0530412static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
413 struct audio_usecase *uc_info)
414{
415 struct listnode *node;
416 struct audio_usecase *usecase;
417
418 if (uc_info == NULL)
419 return -EINVAL;
420
421 /* Re-route all voice usecases on the shared backend other than the
422 specified usecase to new snd devices */
423 list_for_each(node, &adev->usecase_list) {
424 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800425 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530426 enable_audio_route(adev, usecase);
427 }
428 return 0;
429}
430
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700431int pcm_ioctl(struct pcm *pcm, int request, ...)
432{
433 va_list ap;
434 void * arg;
435 int pcm_fd = *(int*)pcm;
436
437 va_start(ap, request);
438 arg = va_arg(ap, void *);
439 va_end(ap);
440
441 return ioctl(pcm_fd, request, arg);
442}
443
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700444int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700445 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800446{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700448 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800449
450 if (usecase == NULL)
451 return -EINVAL;
452
453 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
454
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800455 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700456 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800457 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700458 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800459
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800460#ifdef DS1_DOLBY_DAP_ENABLED
461 audio_extn_dolby_set_dmid(adev);
462 audio_extn_dolby_set_endpoint(adev);
463#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700464 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700465 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530466 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700467 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530468 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800469 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700470 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700471 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700472 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800473 ALOGV("%s: exit", __func__);
474 return 0;
475}
476
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700477int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700478 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700480 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700481 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800482
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530483 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800484 return -EINVAL;
485
486 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700487 if (usecase->type == PCM_CAPTURE)
488 snd_device = usecase->in_snd_device;
489 else
490 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800491 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700492 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700493 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700494 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700495 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530496 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800497 ALOGV("%s: exit", __func__);
498 return 0;
499}
500
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700501int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700502 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800503{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
505
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800506 if (snd_device < SND_DEVICE_MIN ||
507 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800508 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800509 return -EINVAL;
510 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700511
512 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700513
514 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
515 ALOGE("%s: Invalid sound device returned", __func__);
516 return -EINVAL;
517 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700518 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700519 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700520 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 return 0;
522 }
523
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530524
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700525 if (audio_extn_spkr_prot_is_enabled())
526 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700527 /* start usb playback thread */
528 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
529 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
530 audio_extn_usb_start_playback(adev);
531
532 /* start usb capture thread */
533 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
534 audio_extn_usb_start_capture(adev);
535
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800536 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
537 audio_extn_spkr_prot_is_enabled()) {
538 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700539 adev->snd_dev_ref_cnt[snd_device]--;
540 return -EINVAL;
541 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200542 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800543 if (audio_extn_spkr_prot_start_processing(snd_device)) {
544 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200545 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800546 return -EINVAL;
547 }
548 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700549 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700550 /* due to the possibility of calibration overwrite between listen
551 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700552 audio_extn_sound_trigger_update_device_status(snd_device,
553 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530554 audio_extn_listen_update_device_status(snd_device,
555 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700556 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700557 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700558 audio_extn_sound_trigger_update_device_status(snd_device,
559 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530560 audio_extn_listen_update_device_status(snd_device,
561 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700562 return -EINVAL;
563 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300564 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700565 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530566
567 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
568 !adev->native_playback_enabled &&
569 audio_is_true_native_stream_active(adev)) {
570 ALOGD("%s: %d: napb: enabling native mode in hardware",
571 __func__, __LINE__);
572 audio_route_apply_and_update_path(adev->audio_route,
573 "true-native-mode");
574 adev->native_playback_enabled = true;
575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 return 0;
578}
579
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700580int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700581 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700583 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
584
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800585 if (snd_device < SND_DEVICE_MIN ||
586 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800587 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800588 return -EINVAL;
589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
591 ALOGE("%s: device ref cnt is already 0", __func__);
592 return -EINVAL;
593 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700596
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700597 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
598 ALOGE("%s: Invalid sound device returned", __func__);
599 return -EINVAL;
600 }
601
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700602 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700603 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800604 /* exit usb play back thread */
605 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
606 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
607 audio_extn_usb_stop_playback();
608
609 /* exit usb capture thread */
610 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700611 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800612
613 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
614 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700615 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300616 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700617 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300618 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700619
Ashish Jain81eb2a82015-05-13 10:52:34 +0530620 if (snd_device == SND_DEVICE_OUT_HDMI)
621 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530622 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
623 adev->native_playback_enabled) {
624 ALOGD("%s: %d: napb: disabling native mode in hardware",
625 __func__, __LINE__);
626 audio_route_reset_and_update_path(adev->audio_route,
627 "true-native-mode");
628 adev->native_playback_enabled = false;
629 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530630
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200631 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700632 audio_extn_sound_trigger_update_device_status(snd_device,
633 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530634 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800635 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800638 return 0;
639}
640
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530642 struct audio_usecase *uc_info,
643 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644{
645 struct listnode *node;
646 struct audio_usecase *usecase;
647 bool switch_device[AUDIO_USECASE_MAX];
648 int i, num_uc_to_switch = 0;
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530649 int backend_idx = DEFAULT_CODEC_BACKEND;
650 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651
652 /*
653 * This function is to make sure that all the usecases that are active on
654 * the hardware codec backend are always routed to any one device that is
655 * handled by the hardware codec.
656 * For example, if low-latency and deep-buffer usecases are currently active
657 * on speaker and out_set_parameters(headset) is received on low-latency
658 * output, then we have to make sure deep-buffer is also switched to headset,
659 * because of the limitation that both the devices cannot be enabled
660 * at the same time as they share the same backend.
661 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700662 /*
663 * This call is to check if we need to force routing for a particular stream
664 * If there is a backend configuration change for the device when a
665 * new stream starts, then ADM needs to be closed and re-opened with the new
666 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700668 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800669 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
670 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: force routing %d", __func__, force_routing);
673
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530674 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800676 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800677 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 for (i = 0; i < AUDIO_USECASE_MAX; i++)
679 switch_device[i] = false;
680
681 list_for_each(node, &adev->usecase_list) {
682 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800683
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530684 if (usecase == uc_info)
685 continue;
686 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
687
688 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
689 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
690 __func__, i, backend_idx, usecase_backend_idx,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 platform_get_snd_device_name(snd_device),
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530692 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800693
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800694 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashokeaec6392016-04-19 09:37:57 +0530695 (usecase->out_snd_device != snd_device || force_routing) &&
696 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
697 usecase_backend_idx == backend_idx) {
698 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
699 __func__, use_case_table[usecase->id],
700 platform_get_snd_device_name(usecase->out_snd_device));
701 disable_audio_route(adev, usecase);
702 switch_device[usecase->id] = true;
703 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700704 }
705 }
706
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530707 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
708 num_uc_to_switch);
709
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700711 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530713 /* Make sure the previous devices to be disabled first and then enable the
714 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
717 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700718 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 }
720 }
721
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700722 list_for_each(node, &adev->usecase_list) {
723 usecase = node_to_item(node, struct audio_usecase, list);
724 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700726 }
727 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 /* Re-route all the usecases on the shared backend other than the
730 specified usecase to new snd devices */
731 list_for_each(node, &adev->usecase_list) {
732 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530733 /* Update the out_snd_device only before enabling the audio route */
734 if (switch_device[usecase->id]) {
735 usecase->out_snd_device = snd_device;
736 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530737 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530738 use_case_table[usecase->id],
739 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530740 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742 }
743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 }
745}
746
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700747static void check_and_route_capture_usecases(struct audio_device *adev,
748 struct audio_usecase *uc_info,
749 snd_device_t snd_device)
750{
751 struct listnode *node;
752 struct audio_usecase *usecase;
753 bool switch_device[AUDIO_USECASE_MAX];
754 int i, num_uc_to_switch = 0;
755
756 /*
757 * This function is to make sure that all the active capture usecases
758 * are always routed to the same input sound device.
759 * For example, if audio-record and voice-call usecases are currently
760 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
761 * is received for voice call then we have to make sure that audio-record
762 * usecase is also switched to earpiece i.e. voice-dmic-ef,
763 * because of the limitation that two devices cannot be enabled
764 * at the same time if they share the same backend.
765 */
766 for (i = 0; i < AUDIO_USECASE_MAX; i++)
767 switch_device[i] = false;
768
769 list_for_each(node, &adev->usecase_list) {
770 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800771 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700772 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700773 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700774 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530775 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
776 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700777 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
779 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700780 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700781 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700782 switch_device[usecase->id] = true;
783 num_uc_to_switch++;
784 }
785 }
786
787 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700788 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700789
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530790 /* Make sure the previous devices to be disabled first and then enable the
791 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
794 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700795 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800796 }
797 }
798
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
801 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700802 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700803 }
804 }
805
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700806 /* Re-route all the usecases on the shared backend other than the
807 specified usecase to new snd devices */
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
810 /* Update the in_snd_device only before enabling the audio route */
811 if (switch_device[usecase->id] ) {
812 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800813 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530814 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700815 }
816 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700817 }
818}
819
Mingming Yin3a941d42016-02-17 18:08:05 -0800820static void reset_hdmi_sink_caps(struct stream_out *out) {
821 int i = 0;
822
823 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
824 out->supported_channel_masks[i] = 0;
825 }
826 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
827 out->supported_formats[i] = 0;
828 }
829 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
830 out->supported_sample_rates[i] = 0;
831 }
832}
833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800834/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800835static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836{
Mingming Yin3a941d42016-02-17 18:08:05 -0800837 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700838 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839
Mingming Yin3a941d42016-02-17 18:08:05 -0800840 reset_hdmi_sink_caps(out);
841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800843 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800844 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700845 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800846 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
847 case 6:
848 ALOGV("%s: HDMI supports 5.1 channels", __func__);
849 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
850 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
851 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
852 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
853 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
854 case 2:
855 ALOGV("%s: HDMI supports 2 channels", __func__);
856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857 break;
858 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800859 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700860 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800861 break;
862 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800863
864 // check channel format caps
865 i = 0;
866 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
867 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
868 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
869 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
870 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
871 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
872 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
873 }
874
875 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
876 ALOGV(":%s HDMI supports DTS format", __func__);
877 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
878 }
879
880 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
881 ALOGV(":%s HDMI supports DTS HD format", __func__);
882 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
883 }
884
885
886 // check sample rate caps
887 i = 0;
888 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
889 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
890 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
891 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
892 }
893 }
894
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700895 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800896}
897
Alexy Josephb1379942016-01-29 15:49:38 -0800898audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800899 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700900{
901 struct audio_usecase *usecase;
902 struct listnode *node;
903
904 list_for_each(node, &adev->usecase_list) {
905 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800906 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700907 ALOGV("%s: usecase id %d", __func__, usecase->id);
908 return usecase->id;
909 }
910 }
911 return USECASE_INVALID;
912}
913
Alexy Josephb1379942016-01-29 15:49:38 -0800914struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700915 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916{
917 struct audio_usecase *usecase;
918 struct listnode *node;
919
920 list_for_each(node, &adev->usecase_list) {
921 usecase = node_to_item(node, struct audio_usecase, list);
922 if (usecase->id == uc_id)
923 return usecase;
924 }
925 return NULL;
926}
927
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530928/*
929 * is a true native playback active
930 */
931bool audio_is_true_native_stream_active(struct audio_device *adev)
932{
933 bool active = false;
934 int i = 0;
935 struct listnode *node;
936
937 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
938 ALOGV("%s:napb: not in true mode or non hdphones device",
939 __func__);
940 active = false;
941 goto exit;
942 }
943
944 list_for_each(node, &adev->usecase_list) {
945 struct audio_usecase *uc;
946 uc = node_to_item(node, struct audio_usecase, list);
947 struct stream_out *curr_out =
948 (struct stream_out*) uc->stream.out;
949
950 if (curr_out && PCM_PLAYBACK == uc->type) {
951 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
952 "(%d) device %s", __func__, i++, use_case_table[uc->id],
953 uc->id, curr_out->sample_rate,
954 curr_out->bit_width,
955 platform_get_snd_device_name(uc->out_snd_device));
956
957 if (is_offload_usecase(uc->id) &&
958 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
959 active = true;
960 ALOGD("%s:napb:native stream detected", __func__);
961 }
962 }
963 }
964exit:
965 return active;
966}
967
968
969static bool force_device_switch(struct audio_usecase *usecase)
970{
971 bool ret = false;
972 bool is_it_true_mode = false;
973
974 if (is_offload_usecase(usecase->id) &&
975 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800976 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
977 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
978 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530979 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
980 if ((is_it_true_mode && !adev->native_playback_enabled) ||
981 (!is_it_true_mode && adev->native_playback_enabled)){
982 ret = true;
983 ALOGD("napb: time to toggle native mode");
984 }
985 }
986
987 return ret;
988}
989
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700990int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800992 snd_device_t out_snd_device = SND_DEVICE_NONE;
993 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700994 struct audio_usecase *usecase = NULL;
995 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800996 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800997 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800998 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301001 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1002
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 usecase = get_usecase_from_list(adev, uc_id);
1004 if (usecase == NULL) {
1005 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1006 return -EINVAL;
1007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001009 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001010 (usecase->type == VOIP_CALL) ||
1011 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001012 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001013 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001014 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 usecase->devices = usecase->stream.out->devices;
1016 } else {
1017 /*
1018 * If the voice call is active, use the sound devices of voice call usecase
1019 * so that it would not result any device switch. All the usecases will
1020 * be switched to new device when select_devices() is called for voice call
1021 * usecase. This is to avoid switching devices for voice call when
1022 * check_usecases_codec_backend() is called below.
1023 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001024 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001025 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001026 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001027 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1028 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 in_snd_device = vc_usecase->in_snd_device;
1030 out_snd_device = vc_usecase->out_snd_device;
1031 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001032 } else if (voice_extn_compress_voip_is_active(adev)) {
1033 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001034 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301035 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001036 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001037 in_snd_device = voip_usecase->in_snd_device;
1038 out_snd_device = voip_usecase->out_snd_device;
1039 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001040 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001041 hfp_ucid = audio_extn_hfp_get_usecase();
1042 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001043 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001044 in_snd_device = hfp_usecase->in_snd_device;
1045 out_snd_device = hfp_usecase->out_snd_device;
1046 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 }
1048 if (usecase->type == PCM_PLAYBACK) {
1049 usecase->devices = usecase->stream.out->devices;
1050 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001051 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001052 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001053 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001054 if (usecase->stream.out == adev->primary_output &&
1055 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001056 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001057 select_devices(adev, adev->active_input->usecase);
1058 }
1059 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 } else if (usecase->type == PCM_CAPTURE) {
1061 usecase->devices = usecase->stream.in->device;
1062 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001063 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001064 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001065 if (adev->active_input &&
1066 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301067 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1068 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1069 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001070 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001071 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001072 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1073 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001074 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001075 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001076 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 }
1078 }
1079
1080 if (out_snd_device == usecase->out_snd_device &&
1081 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301082
1083 if (!force_device_switch(usecase))
1084 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085 }
1086
sangwoobc677242013-08-08 16:53:43 +09001087 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001088 out_snd_device, platform_get_snd_device_name(out_snd_device),
1089 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 /*
1092 * Limitation: While in call, to do a device switch we need to disable
1093 * and enable both RX and TX devices though one of them is same as current
1094 * device.
1095 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001096 if ((usecase->type == VOICE_CALL) &&
1097 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1098 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001099 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001100 }
1101
1102 if (((usecase->type == VOICE_CALL) ||
1103 (usecase->type == VOIP_CALL)) &&
1104 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1105 /* Disable sidetone only if voice/voip call already exists */
1106 if (voice_is_call_state_active(adev) ||
1107 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001108 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001109 }
1110
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 /* Disable current sound devices */
1112 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 disable_audio_route(adev, usecase);
1114 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 }
1116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001118 disable_audio_route(adev, usecase);
1119 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 }
1121
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001122 /* Applicable only on the targets that has external modem.
1123 * New device information should be sent to modem before enabling
1124 * the devices to reduce in-call device switch time.
1125 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001126 if ((usecase->type == VOICE_CALL) &&
1127 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1128 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001129 status = platform_switch_voice_call_enable_device_config(adev->platform,
1130 out_snd_device,
1131 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001132 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001133
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 /* Enable new sound devices */
1135 if (out_snd_device != SND_DEVICE_NONE) {
1136 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1137 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001138 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 }
1140
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001141 if (in_snd_device != SND_DEVICE_NONE) {
1142 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001143 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001144 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145
Avinash Vaish71a8b972014-07-24 15:36:33 +05301146 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001147 status = platform_switch_voice_call_device_post(adev->platform,
1148 out_snd_device,
1149 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301150 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001151 /* Enable sidetone only if voice/voip call already exists */
1152 if (voice_is_call_state_active(adev) ||
1153 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001154 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301155 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001156
sangwoo170731f2013-06-08 15:36:36 +09001157 usecase->in_snd_device = in_snd_device;
1158 usecase->out_snd_device = out_snd_device;
1159
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301160 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001161 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301162 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001163 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301164 usecase->stream.out->flags,
1165 usecase->stream.out->format,
1166 usecase->stream.out->sample_rate,
1167 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301168 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301169 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001170 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301171 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001172
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001173 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001174
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001175 /* Applicable only on the targets that has external modem.
1176 * Enable device command should be sent to modem only after
1177 * enabling voice call mixer controls
1178 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001179 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001180 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1181 out_snd_device,
1182 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301183 ALOGD("%s: done",__func__);
1184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001185 return status;
1186}
1187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188static int stop_input_stream(struct stream_in *in)
1189{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301190 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001191 struct audio_usecase *uc_info;
1192 struct audio_device *adev = in->dev;
1193
Eric Laurentc8400632013-02-14 19:04:54 -08001194 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195
Eric Laurent994a6932013-07-17 11:51:42 -07001196 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001197 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 uc_info = get_usecase_from_list(adev, in->usecase);
1199 if (uc_info == NULL) {
1200 ALOGE("%s: Could not find the usecase (%d) in the list",
1201 __func__, in->usecase);
1202 return -EINVAL;
1203 }
1204
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001205 /* Close in-call recording streams */
1206 voice_check_and_stop_incall_rec_usecase(adev, in);
1207
Eric Laurent150dbfe2013-02-27 14:31:02 -08001208 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001209 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210
1211 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001212 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001213
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001214 list_remove(&uc_info->list);
1215 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216
Eric Laurent994a6932013-07-17 11:51:42 -07001217 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218 return ret;
1219}
1220
1221int start_input_stream(struct stream_in *in)
1222{
1223 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001224 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 struct audio_usecase *uc_info;
1226 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301227 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228
Mingming Yin2664a5b2015-09-03 10:53:11 -07001229 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1230 if (get_usecase_from_list(adev, usecase) == NULL)
1231 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301232 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1233 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001234
Naresh Tanniru80659832014-06-04 18:17:56 +05301235
1236 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301237 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301238 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301239 goto error_config;
1240 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301241
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001242 /* Check if source matches incall recording usecase criteria */
1243 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1244 if (ret)
1245 goto error_config;
1246 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001247 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1248
1249 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1250 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1251 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1252 goto error_config;
1253 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001254
Eric Laurentb23d5282013-05-14 15:27:20 -07001255 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001256 if (in->pcm_device_id < 0) {
1257 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1258 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001259 ret = -EINVAL;
1260 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262
1263 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001265
1266 if (!uc_info) {
1267 ret = -ENOMEM;
1268 goto error_config;
1269 }
1270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 uc_info->id = in->usecase;
1272 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001273 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 uc_info->devices = in->device;
1275 uc_info->in_snd_device = SND_DEVICE_NONE;
1276 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001278 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301279 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1280 adev->perf_lock_opts,
1281 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283
Eric Laurentc8400632013-02-14 19:04:54 -08001284 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001285 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1286
1287 unsigned int flags = PCM_IN;
1288 unsigned int pcm_open_retry_count = 0;
1289
1290 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1291 flags |= PCM_MMAP | PCM_NOIRQ;
1292 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1293 }
1294
1295 while (1) {
1296 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1297 flags, &in->config);
1298 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1299 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1300 if (in->pcm != NULL) {
1301 pcm_close(in->pcm);
1302 in->pcm = NULL;
1303 }
1304 if (pcm_open_retry_count-- == 0) {
1305 ret = -EIO;
1306 goto error_open;
1307 }
1308 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1309 continue;
1310 }
1311 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001313
1314 ALOGV("%s: pcm_prepare", __func__);
1315 ret = pcm_prepare(in->pcm);
1316 if (ret < 0) {
1317 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1318 pcm_close(in->pcm);
1319 in->pcm = NULL;
1320 goto error_open;
1321 }
1322
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301323 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001324 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001325
Eric Laurentc8400632013-02-14 19:04:54 -08001326 return ret;
1327
1328error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301329 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001331error_config:
1332 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301333 /*
1334 * sleep 50ms to allow sufficient time for kernel
1335 * drivers to recover incases like SSR.
1336 */
1337 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001339
1340 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341}
1342
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001343void lock_input_stream(struct stream_in *in)
1344{
1345 pthread_mutex_lock(&in->pre_lock);
1346 pthread_mutex_lock(&in->lock);
1347 pthread_mutex_unlock(&in->pre_lock);
1348}
1349
1350void lock_output_stream(struct stream_out *out)
1351{
1352 pthread_mutex_lock(&out->pre_lock);
1353 pthread_mutex_lock(&out->lock);
1354 pthread_mutex_unlock(&out->pre_lock);
1355}
1356
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001357/* must be called with out->lock locked */
1358static int send_offload_cmd_l(struct stream_out* out, int command)
1359{
1360 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1361
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001362 if (!cmd) {
1363 ALOGE("failed to allocate mem for command 0x%x", command);
1364 return -ENOMEM;
1365 }
1366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001367 ALOGVV("%s %d", __func__, command);
1368
1369 cmd->cmd = command;
1370 list_add_tail(&out->offload_cmd_list, &cmd->node);
1371 pthread_cond_signal(&out->offload_cond);
1372 return 0;
1373}
1374
1375/* must be called iwth out->lock locked */
1376static void stop_compressed_output_l(struct stream_out *out)
1377{
1378 out->offload_state = OFFLOAD_STATE_IDLE;
1379 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001380 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381 if (out->compr != NULL) {
1382 compress_stop(out->compr);
1383 while (out->offload_thread_blocked) {
1384 pthread_cond_wait(&out->cond, &out->lock);
1385 }
1386 }
1387}
1388
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001389bool is_offload_usecase(audio_usecase_t uc_id)
1390{
1391 unsigned int i;
1392 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1393 if (uc_id == offload_usecases[i])
1394 return true;
1395 }
1396 return false;
1397}
1398
vivek mehta446c3962015-09-14 10:57:35 -07001399static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001400{
vivek mehta446c3962015-09-14 10:57:35 -07001401 audio_usecase_t ret_uc = USECASE_INVALID;
1402 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001403 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001404 if (!adev->multi_offload_enable) {
1405 if (is_direct_pcm)
1406 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1407 else
1408 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001409
vivek mehta446c3962015-09-14 10:57:35 -07001410 pthread_mutex_lock(&adev->lock);
1411 if (get_usecase_from_list(adev, ret_uc) != NULL)
1412 ret_uc = USECASE_INVALID;
1413 pthread_mutex_unlock(&adev->lock);
1414
1415 return ret_uc;
1416 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001417
1418 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001419 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1420 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1421 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1422 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001423 break;
1424 }
1425 }
vivek mehta446c3962015-09-14 10:57:35 -07001426
1427 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1428 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001429}
1430
1431static void free_offload_usecase(struct audio_device *adev,
1432 audio_usecase_t uc_id)
1433{
vivek mehta446c3962015-09-14 10:57:35 -07001434 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001435 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001436
1437 if (!adev->multi_offload_enable)
1438 return;
1439
1440 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1441 if (offload_usecases[offload_uc_index] == uc_id) {
1442 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001443 break;
1444 }
1445 }
1446 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1447}
1448
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449static void *offload_thread_loop(void *context)
1450{
1451 struct stream_out *out = (struct stream_out *) context;
1452 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001453 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001454
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001455 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1456 set_sched_policy(0, SP_FOREGROUND);
1457 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1458
1459 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001461 for (;;) {
1462 struct offload_cmd *cmd = NULL;
1463 stream_callback_event_t event;
1464 bool send_callback = false;
1465
1466 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1467 __func__, list_empty(&out->offload_cmd_list),
1468 out->offload_state);
1469 if (list_empty(&out->offload_cmd_list)) {
1470 ALOGV("%s SLEEPING", __func__);
1471 pthread_cond_wait(&out->offload_cond, &out->lock);
1472 ALOGV("%s RUNNING", __func__);
1473 continue;
1474 }
1475
1476 item = list_head(&out->offload_cmd_list);
1477 cmd = node_to_item(item, struct offload_cmd, node);
1478 list_remove(item);
1479
1480 ALOGVV("%s STATE %d CMD %d out->compr %p",
1481 __func__, out->offload_state, cmd->cmd, out->compr);
1482
1483 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1484 free(cmd);
1485 break;
1486 }
1487
1488 if (out->compr == NULL) {
1489 ALOGE("%s: Compress handle is NULL", __func__);
1490 pthread_cond_signal(&out->cond);
1491 continue;
1492 }
1493 out->offload_thread_blocked = true;
1494 pthread_mutex_unlock(&out->lock);
1495 send_callback = false;
1496 switch(cmd->cmd) {
1497 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001498 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001499 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001500 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001501 send_callback = true;
1502 event = STREAM_CBK_EVENT_WRITE_READY;
1503 break;
1504 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001505 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301506 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001507 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301508 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001509 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301510 if (ret < 0)
1511 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301512 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301513 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001514 compress_drain(out->compr);
1515 else
1516 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301517 if (ret != -ENETRESET) {
1518 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301519 pthread_mutex_lock(&out->lock);
1520 out->send_new_metadata = 1;
1521 out->send_next_track_params = true;
1522 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301523 event = STREAM_CBK_EVENT_DRAIN_READY;
1524 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1525 } else
1526 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001527 break;
1528 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001529 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001530 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001531 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001532 send_callback = true;
1533 event = STREAM_CBK_EVENT_DRAIN_READY;
1534 break;
1535 default:
1536 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1537 break;
1538 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001539 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 out->offload_thread_blocked = false;
1541 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001542 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001543 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001544 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001545 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001546 free(cmd);
1547 }
1548
1549 pthread_cond_signal(&out->cond);
1550 while (!list_empty(&out->offload_cmd_list)) {
1551 item = list_head(&out->offload_cmd_list);
1552 list_remove(item);
1553 free(node_to_item(item, struct offload_cmd, node));
1554 }
1555 pthread_mutex_unlock(&out->lock);
1556
1557 return NULL;
1558}
1559
1560static int create_offload_callback_thread(struct stream_out *out)
1561{
1562 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1563 list_init(&out->offload_cmd_list);
1564 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1565 offload_thread_loop, out);
1566 return 0;
1567}
1568
1569static int destroy_offload_callback_thread(struct stream_out *out)
1570{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001571 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572 stop_compressed_output_l(out);
1573 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1574
1575 pthread_mutex_unlock(&out->lock);
1576 pthread_join(out->offload_thread, (void **) NULL);
1577 pthread_cond_destroy(&out->offload_cond);
1578
1579 return 0;
1580}
1581
Eric Laurent07eeafd2013-10-06 12:52:49 -07001582static bool allow_hdmi_channel_config(struct audio_device *adev)
1583{
1584 struct listnode *node;
1585 struct audio_usecase *usecase;
1586 bool ret = true;
1587
1588 list_for_each(node, &adev->usecase_list) {
1589 usecase = node_to_item(node, struct audio_usecase, list);
1590 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1591 /*
1592 * If voice call is already existing, do not proceed further to avoid
1593 * disabling/enabling both RX and TX devices, CSD calls, etc.
1594 * Once the voice call done, the HDMI channels can be configured to
1595 * max channels of remaining use cases.
1596 */
1597 if (usecase->id == USECASE_VOICE_CALL) {
1598 ALOGD("%s: voice call is active, no change in HDMI channels",
1599 __func__);
1600 ret = false;
1601 break;
1602 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1603 ALOGD("%s: multi channel playback is active, "
1604 "no change in HDMI channels", __func__);
1605 ret = false;
1606 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001607 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001608 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001609 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1610 ", no change in HDMI channels", __func__,
1611 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001612 ret = false;
1613 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001614 }
1615 }
1616 }
1617 return ret;
1618}
1619
1620static int check_and_set_hdmi_channels(struct audio_device *adev,
1621 unsigned int channels)
1622{
1623 struct listnode *node;
1624 struct audio_usecase *usecase;
1625
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001626 unsigned int supported_channels = platform_edid_get_max_channels(
1627 adev->platform);
1628 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001629 /* Check if change in HDMI channel config is allowed */
1630 if (!allow_hdmi_channel_config(adev))
1631 return 0;
1632
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001633 if (channels > supported_channels)
1634 channels = supported_channels;
1635
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001637 ALOGD("%s: Requested channels are same as current channels(%d)",
1638 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001639 return 0;
1640 }
1641
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001642 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001643 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001644 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001645 adev->cur_hdmi_channels = channels;
1646
1647 /*
1648 * Deroute all the playback streams routed to HDMI so that
1649 * the back end is deactivated. Note that backend will not
1650 * be deactivated if any one stream is connected to it.
1651 */
1652 list_for_each(node, &adev->usecase_list) {
1653 usecase = node_to_item(node, struct audio_usecase, list);
1654 if (usecase->type == PCM_PLAYBACK &&
1655 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001656 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001657 }
1658 }
1659
1660 /*
1661 * Enable all the streams disabled above. Now the HDMI backend
1662 * will be activated with new channel configuration
1663 */
1664 list_for_each(node, &adev->usecase_list) {
1665 usecase = node_to_item(node, struct audio_usecase, list);
1666 if (usecase->type == PCM_PLAYBACK &&
1667 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001668 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001669 }
1670 }
1671
1672 return 0;
1673}
1674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675static int stop_output_stream(struct stream_out *out)
1676{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301677 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678 struct audio_usecase *uc_info;
1679 struct audio_device *adev = out->dev;
1680
Eric Laurent994a6932013-07-17 11:51:42 -07001681 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683 uc_info = get_usecase_from_list(adev, out->usecase);
1684 if (uc_info == NULL) {
1685 ALOGE("%s: Could not find the usecase (%d) in the list",
1686 __func__, out->usecase);
1687 return -EINVAL;
1688 }
1689
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001690 if (is_offload_usecase(out->usecase) &&
1691 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001692 if (adev->visualizer_stop_output != NULL)
1693 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001694
1695 audio_extn_dts_remove_state_notifier_node(out->usecase);
1696
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001697 if (adev->offload_effects_stop_output != NULL)
1698 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1699 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001700
Eric Laurent150dbfe2013-02-27 14:31:02 -08001701 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001702 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001703
1704 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001705 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001707 list_remove(&uc_info->list);
1708 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001710 if (is_offload_usecase(out->usecase) &&
1711 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1712 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1713 ALOGV("Disable passthrough , reset mixer to pcm");
1714 /* NO_PASSTHROUGH */
1715 out->compr_config.codec->compr_passthr = 0;
Mingming Yin3a941d42016-02-17 18:08:05 -08001716 platform_set_hdmi_config(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001717 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1718 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001719 /* Must be called after removing the usecase from list */
1720 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1721 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1722
Eric Laurent994a6932013-07-17 11:51:42 -07001723 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724 return ret;
1725}
1726
1727int start_output_stream(struct stream_out *out)
1728{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001730 int sink_channels = 0;
1731 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 struct audio_usecase *uc_info;
1733 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301734 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001736 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1737 ret = -EINVAL;
1738 goto error_config;
1739 }
1740
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301741 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1742 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1743 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301744
Naresh Tanniru80659832014-06-04 18:17:56 +05301745 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301746 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301747 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301748 goto error_config;
1749 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301750
Eric Laurentb23d5282013-05-14 15:27:20 -07001751 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 if (out->pcm_device_id < 0) {
1753 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1754 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001755 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001756 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757 }
1758
1759 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001760
1761 if (!uc_info) {
1762 ret = -ENOMEM;
1763 goto error_config;
1764 }
1765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 uc_info->id = out->usecase;
1767 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001768 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001769 uc_info->devices = out->devices;
1770 uc_info->in_snd_device = SND_DEVICE_NONE;
1771 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001772 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001773 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001774 if (is_offload_usecase(out->usecase)) {
1775 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001776 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1777 }
1778 }
Mingming Yin9c041392014-05-01 15:37:31 -07001779 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1780 if (!strncmp("true", prop_value, 4)) {
1781 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001782 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1783 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001784 check_and_set_hdmi_channels(adev, sink_channels);
1785 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001786 if (is_offload_usecase(out->usecase)) {
1787 unsigned int ch_count = out->compr_config.codec->ch_in;
1788 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1789 /* backend channel config for passthrough stream is stereo */
1790 ch_count = 2;
1791 check_and_set_hdmi_channels(adev, ch_count);
1792 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001793 check_and_set_hdmi_channels(adev, out->config.channels);
1794 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001795 platform_set_hdmi_config(out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001796 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001797 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301799 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1800 adev->perf_lock_opts,
1801 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802 select_devices(adev, out->usecase);
1803
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001804 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1805 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001806 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001807 unsigned int flags = PCM_OUT;
1808 unsigned int pcm_open_retry_count = 0;
1809 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1810 flags |= PCM_MMAP | PCM_NOIRQ;
1811 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1812 } else
1813 flags |= PCM_MONOTONIC;
1814
1815 while (1) {
1816 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1817 flags, &out->config);
1818 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1819 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1820 if (out->pcm != NULL) {
1821 pcm_close(out->pcm);
1822 out->pcm = NULL;
1823 }
1824 if (pcm_open_retry_count-- == 0) {
1825 ret = -EIO;
1826 goto error_open;
1827 }
1828 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1829 continue;
1830 }
1831 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001832 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001833
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001834 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1835 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001836
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001837 ALOGV("%s: pcm_prepare", __func__);
1838 if (pcm_is_ready(out->pcm)) {
1839 ret = pcm_prepare(out->pcm);
1840 if (ret < 0) {
1841 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1842 pcm_close(out->pcm);
1843 out->pcm = NULL;
1844 goto error_open;
1845 }
1846 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001848 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1849 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001851 out->compr = compress_open(adev->snd_card,
1852 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001853 COMPRESS_IN, &out->compr_config);
1854 if (out->compr && !is_compress_ready(out->compr)) {
1855 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1856 compress_close(out->compr);
1857 out->compr = NULL;
1858 ret = -EIO;
1859 goto error_open;
1860 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301861 /* compress_open sends params of the track, so reset the flag here */
1862 out->is_compr_metadata_avail = false;
1863
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 if (out->offload_callback)
1865 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001866
Fred Oh3f43e742015-03-04 18:42:34 -08001867 /* Since small bufs uses blocking writes, a write will be blocked
1868 for the default max poll time (20s) in the event of an SSR.
1869 Reduce the poll time to observe and deal with SSR faster.
1870 */
1871 if (out->use_small_bufs) {
1872 compress_set_max_poll_wait(out->compr, 1000);
1873 }
1874
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001875 audio_extn_dts_create_state_notifier_node(out->usecase);
1876 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1877 popcount(out->channel_mask),
1878 out->playback_started);
1879
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001880#ifdef DS1_DOLBY_DDP_ENABLED
1881 if (audio_extn_is_dolby_format(out->format))
1882 audio_extn_dolby_send_ddp_endp_params(adev);
1883#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001884 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1885 if (adev->visualizer_start_output != NULL)
1886 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1887 if (adev->offload_effects_start_output != NULL)
1888 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001889 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001890 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301892 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001893 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301897 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001899error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301900 /*
1901 * sleep 50ms to allow sufficient time for kernel
1902 * drivers to recover incases like SSR.
1903 */
1904 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001905 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906}
1907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908static int check_input_parameters(uint32_t sample_rate,
1909 audio_format_t format,
1910 int channel_count)
1911{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001912 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001914 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001915 !voice_extn_compress_voip_is_format_supported(format) &&
1916 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001917
1918 switch (channel_count) {
1919 case 1:
1920 case 2:
1921 case 6:
1922 break;
1923 default:
1924 ret = -EINVAL;
1925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926
1927 switch (sample_rate) {
1928 case 8000:
1929 case 11025:
1930 case 12000:
1931 case 16000:
1932 case 22050:
1933 case 24000:
1934 case 32000:
1935 case 44100:
1936 case 48000:
1937 break;
1938 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001939 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 }
1941
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001942 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943}
1944
1945static size_t get_input_buffer_size(uint32_t sample_rate,
1946 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001947 int channel_count,
1948 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949{
1950 size_t size = 0;
1951
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001952 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1953 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001955 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001956 if (is_low_latency)
1957 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001958 /* ToDo: should use frame_size computed based on the format and
1959 channel_count here. */
1960 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001962 /* make sure the size is multiple of 32 bytes
1963 * At 48 kHz mono 16-bit PCM:
1964 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1965 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1966 */
1967 size += 0x1f;
1968 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001969
1970 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971}
1972
1973static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1974{
1975 struct stream_out *out = (struct stream_out *)stream;
1976
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001977 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978}
1979
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001980static int out_set_sample_rate(struct audio_stream *stream __unused,
1981 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982{
1983 return -ENOSYS;
1984}
1985
1986static size_t out_get_buffer_size(const struct audio_stream *stream)
1987{
1988 struct stream_out *out = (struct stream_out *)stream;
1989
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001990 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001992 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1993 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001994
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001995 return out->config.period_size *
1996 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997}
1998
1999static uint32_t out_get_channels(const struct audio_stream *stream)
2000{
2001 struct stream_out *out = (struct stream_out *)stream;
2002
2003 return out->channel_mask;
2004}
2005
2006static audio_format_t out_get_format(const struct audio_stream *stream)
2007{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002008 struct stream_out *out = (struct stream_out *)stream;
2009
2010 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011}
2012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002013static int out_set_format(struct audio_stream *stream __unused,
2014 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015{
2016 return -ENOSYS;
2017}
2018
2019static int out_standby(struct audio_stream *stream)
2020{
2021 struct stream_out *out = (struct stream_out *)stream;
2022 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002023
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302024 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2025 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002026 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2027 /* Ignore standby in case of voip call because the voip output
2028 * stream is closed in adev_close_output_stream()
2029 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302030 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002031 return 0;
2032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002034 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002036 if (adev->adm_deregister_stream)
2037 adev->adm_deregister_stream(adev->adm_data, out->handle);
2038
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002039 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002041 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 if (out->pcm) {
2043 pcm_close(out->pcm);
2044 out->pcm = NULL;
2045 }
2046 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002047 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302049 out->send_next_track_params = false;
2050 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002051 out->gapless_mdata.encoder_delay = 0;
2052 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 if (out->compr != NULL) {
2054 compress_close(out->compr);
2055 out->compr = NULL;
2056 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002057 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002059 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 }
2061 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302062 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 return 0;
2064}
2065
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002066static int out_dump(const struct audio_stream *stream __unused,
2067 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068{
2069 return 0;
2070}
2071
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002072static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2073{
2074 int ret = 0;
2075 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002076
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002077 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002078 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002079 return -EINVAL;
2080 }
2081
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302082 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002083
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002084 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2085 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302086 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002087 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002088 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2089 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302090 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002091 }
2092
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002093 ALOGV("%s new encoder delay %u and padding %u", __func__,
2094 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2095
2096 return 0;
2097}
2098
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002099static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2100{
2101 return out == adev->primary_output || out == adev->voice_tx_output;
2102}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2105{
2106 struct stream_out *out = (struct stream_out *)stream;
2107 struct audio_device *adev = out->dev;
2108 struct str_parms *parms;
2109 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002110 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111
sangwoobc677242013-08-08 16:53:43 +09002112 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002113 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302115 if (!parms)
2116 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002117 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2118 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002120 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002121 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002123 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302124 * When HDMI cable is unplugged/usb hs is disconnected the
2125 * music playback is paused and the policy manager sends routing=0
2126 * But the audioflingercontinues to write data until standby time
2127 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002128 * Avoid this by routing audio to speaker until standby.
2129 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302130 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2131 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002132 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002133 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2134 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002135 }
2136
2137 /*
2138 * select_devices() call below switches all the usecases on the same
2139 * backend to the new device. Refer to check_usecases_codec_backend() in
2140 * the select_devices(). But how do we undo this?
2141 *
2142 * For example, music playback is active on headset (deep-buffer usecase)
2143 * and if we go to ringtones and select a ringtone, low-latency usecase
2144 * will be started on headset+speaker. As we can't enable headset+speaker
2145 * and headset devices at the same time, select_devices() switches the music
2146 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2147 * So when the ringtone playback is completed, how do we undo the same?
2148 *
2149 * We are relying on the out_set_parameters() call on deep-buffer output,
2150 * once the ringtone playback is ended.
2151 * NOTE: We should not check if the current devices are same as new devices.
2152 * Because select_devices() must be called to switch back the music
2153 * playback to headset.
2154 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002155 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002156 out->devices = val;
2157
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302158 if (!out->standby) {
2159 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2160 adev->perf_lock_opts,
2161 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002162 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302163 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2164 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002165
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002166 if (output_drives_call(adev, out)) {
2167 if(!voice_is_in_call(adev)) {
2168 if (adev->mode == AUDIO_MODE_IN_CALL) {
2169 adev->current_call_output = out;
2170 ret = voice_start_call(adev);
2171 }
2172 } else {
2173 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002174 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002175 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002176 }
2177 }
2178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002180 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002182
2183 if (out == adev->primary_output) {
2184 pthread_mutex_lock(&adev->lock);
2185 audio_extn_set_parameters(adev, parms);
2186 pthread_mutex_unlock(&adev->lock);
2187 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002188 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002189 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002190 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002191
2192 audio_extn_dts_create_state_notifier_node(out->usecase);
2193 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2194 popcount(out->channel_mask),
2195 out->playback_started);
2196
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002197 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002198 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302201error:
Eric Laurent994a6932013-07-17 11:51:42 -07002202 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 return ret;
2204}
2205
2206static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2207{
2208 struct stream_out *out = (struct stream_out *)stream;
2209 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002210 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 char value[256];
2212 struct str_parms *reply = str_parms_create();
2213 size_t i, j;
2214 int ret;
2215 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002216
2217 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002218 if (reply) {
2219 str_parms_destroy(reply);
2220 }
2221 if (query) {
2222 str_parms_destroy(query);
2223 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002224 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2225 return NULL;
2226 }
2227
Eric Laurent994a6932013-07-17 11:51:42 -07002228 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2230 if (ret >= 0) {
2231 value[0] = '\0';
2232 i = 0;
2233 while (out->supported_channel_masks[i] != 0) {
2234 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2235 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2236 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002237 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002239 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 first = false;
2241 break;
2242 }
2243 }
2244 i++;
2245 }
2246 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2247 str = str_parms_to_str(reply);
2248 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002249 voice_extn_out_get_parameters(out, query, reply);
2250 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002251 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002252 free(str);
2253 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002256
Alexy Joseph62142aa2015-11-16 15:10:34 -08002257
2258 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2259 if (ret >= 0) {
2260 value[0] = '\0';
2261 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2262 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302263 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002264 } else {
2265 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302266 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002267 }
2268 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002269 if (str)
2270 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002271 str = str_parms_to_str(reply);
2272 }
2273
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002274 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2275 if (ret >= 0) {
2276 value[0] = '\0';
2277 i = 0;
2278 first = true;
2279 while (out->supported_formats[i] != 0) {
2280 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2281 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2282 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002283 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002284 }
2285 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2286 first = false;
2287 break;
2288 }
2289 }
2290 i++;
2291 }
2292 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002293 if (str)
2294 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002295 str = str_parms_to_str(reply);
2296 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002297
2298 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2299 if (ret >= 0) {
2300 value[0] = '\0';
2301 i = 0;
2302 first = true;
2303 while (out->supported_sample_rates[i] != 0) {
2304 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2305 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2306 if (!first) {
2307 strlcat(value, "|", sizeof(value));
2308 }
2309 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2310 first = false;
2311 break;
2312 }
2313 }
2314 i++;
2315 }
2316 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2317 if (str)
2318 free(str);
2319 str = str_parms_to_str(reply);
2320 }
2321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322 str_parms_destroy(query);
2323 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002324 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325 return str;
2326}
2327
2328static uint32_t out_get_latency(const struct audio_stream_out *stream)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002331 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332
Alexy Josephaa54c872014-12-03 02:46:47 -08002333 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002334 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002335 } else {
2336 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002338 }
2339
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302340 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002341 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342}
2343
2344static int out_set_volume(struct audio_stream_out *stream, float left,
2345 float right)
2346{
Eric Laurenta9024de2013-04-04 09:19:12 -07002347 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 int volume[2];
2349
Eric Laurenta9024de2013-04-04 09:19:12 -07002350 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2351 /* only take left channel into account: the API is for stereo anyway */
2352 out->muted = (left == 0.0f);
2353 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002354 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002355 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2356 /*
2357 * Set mute or umute on HDMI passthrough stream.
2358 * Only take left channel into account.
2359 * Mute is 0 and unmute 1
2360 */
2361 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2362 } else {
2363 char mixer_ctl_name[128];
2364 struct audio_device *adev = out->dev;
2365 struct mixer_ctl *ctl;
2366 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002367 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002369 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2370 "Compress Playback %d Volume", pcm_device_id);
2371 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2372 if (!ctl) {
2373 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2374 __func__, mixer_ctl_name);
2375 return -EINVAL;
2376 }
2377 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2378 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2379 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2380 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002382 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 return -ENOSYS;
2385}
2386
2387static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2388 size_t bytes)
2389{
2390 struct stream_out *out = (struct stream_out *)stream;
2391 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302392 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002393 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002395 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302396
Naresh Tanniru80659832014-06-04 18:17:56 +05302397 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002398
Ashish Jainbbce4322016-02-16 13:25:27 +05302399 if (is_offload_usecase(out->usecase)) {
2400 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302401 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2402 pthread_mutex_unlock(&out->lock);
2403 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302404 } else {
2405 /* increase written size during SSR to avoid mismatch
2406 * with the written frames count in AF
2407 */
2408 out->written += bytes / (out->config.channels * sizeof(short));
2409 ALOGD(" %s: sound card is not active/SSR state", __func__);
2410 ret= -EIO;
2411 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302412 }
2413 }
2414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002416 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002417 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002418 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2419 ret = voice_extn_compress_voip_start_output_stream(out);
2420 else
2421 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002422 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002425 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 goto exit;
2427 }
vivek mehta446c3962015-09-14 10:57:35 -07002428 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002429 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431
Ashish Jain81eb2a82015-05-13 10:52:34 +05302432 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002433 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302434 adev->is_channel_status_set = true;
2435 }
2436
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002437 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002438 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002439 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002440 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002441 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2442 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302443 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2444 ALOGD("copl(%p):send next track params in gapless", out);
2445 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2446 out->send_next_track_params = false;
2447 out->is_compr_metadata_avail = false;
2448 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002449 }
2450
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302452 if (ret < 0)
2453 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302454 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002455 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302456 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302458 } else if (-ENETRESET == ret) {
2459 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2460 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2461 pthread_mutex_unlock(&out->lock);
2462 out_standby(&out->stream.common);
2463 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002464 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302465 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002467 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 out->playback_started = 1;
2469 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002470
2471 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2472 popcount(out->channel_mask),
2473 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002474 }
2475 pthread_mutex_unlock(&out->lock);
2476 return ret;
2477 } else {
2478 if (out->pcm) {
2479 if (out->muted)
2480 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002481
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302482 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002483
2484 if (adev->adm_request_focus)
2485 adev->adm_request_focus(adev->adm_data, out->handle);
2486
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002487 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2488 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2489 else
2490 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002491
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302492 if (ret < 0)
2493 ret = -errno;
2494 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002495 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002496
2497 if (adev->adm_abandon_focus)
2498 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 }
2501
2502exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302503 /* ToDo: There may be a corner case when SSR happens back to back during
2504 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302505 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302506 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302507 }
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 pthread_mutex_unlock(&out->lock);
2510
2511 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002512 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002513 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302514 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302515 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302516 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302517 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302518 out->standby = true;
2519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302521 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302522 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 }
2524 return bytes;
2525}
2526
2527static int out_get_render_position(const struct audio_stream_out *stream,
2528 uint32_t *dsp_frames)
2529{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302531 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002532
2533 if (dsp_frames == NULL)
2534 return -EINVAL;
2535
2536 *dsp_frames = 0;
2537 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002538 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002539 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002540 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302541 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002542 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302543 if (ret < 0)
2544 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002545 ALOGVV("%s rendered frames %d sample_rate %d",
2546 __func__, *dsp_frames, out->sample_rate);
2547 }
2548 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302549 if (-ENETRESET == ret) {
2550 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2551 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2552 return -EINVAL;
2553 } else if(ret < 0) {
2554 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2555 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302556 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2557 /*
2558 * Handle corner case where compress session is closed during SSR
2559 * and timestamp is queried
2560 */
2561 ALOGE(" ERROR: sound card not active, return error");
2562 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302563 } else {
2564 return 0;
2565 }
Zhou Song32a556e2015-05-05 10:46:56 +08002566 } else if (audio_is_linear_pcm(out->format)) {
2567 *dsp_frames = out->written;
2568 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002569 } else
2570 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571}
2572
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002573static int out_add_audio_effect(const struct audio_stream *stream __unused,
2574 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575{
2576 return 0;
2577}
2578
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002579static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2580 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581{
2582 return 0;
2583}
2584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002585static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2586 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 return -EINVAL;
2589}
2590
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002591static int out_get_presentation_position(const struct audio_stream_out *stream,
2592 uint64_t *frames, struct timespec *timestamp)
2593{
2594 struct stream_out *out = (struct stream_out *)stream;
2595 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002596 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002597
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002598 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002599
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002600 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002601 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302602 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002603 &out->sample_rate);
2604 ALOGVV("%s rendered frames %ld sample_rate %d",
2605 __func__, dsp_frames, out->sample_rate);
2606 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302607 if (ret < 0)
2608 ret = -errno;
2609 if (-ENETRESET == ret) {
2610 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2611 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2612 ret = -EINVAL;
2613 } else
2614 ret = 0;
2615
Eric Laurent949a0892013-09-20 09:20:13 -07002616 /* this is the best we can do */
2617 clock_gettime(CLOCK_MONOTONIC, timestamp);
2618 }
2619 } else {
2620 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002621 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002622 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2623 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002624 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002625 // This adjustment accounts for buffering after app processor.
2626 // It is based on estimated DSP latency per use case, rather than exact.
2627 signed_frames -=
2628 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2629
Eric Laurent949a0892013-09-20 09:20:13 -07002630 // It would be unusual for this value to be negative, but check just in case ...
2631 if (signed_frames >= 0) {
2632 *frames = signed_frames;
2633 ret = 0;
2634 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002635 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302636 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2637 *frames = out->written;
2638 clock_gettime(CLOCK_MONOTONIC, timestamp);
2639 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002640 }
2641 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002642 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002643 return ret;
2644}
2645
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002646static int out_set_callback(struct audio_stream_out *stream,
2647 stream_callback_t callback, void *cookie)
2648{
2649 struct stream_out *out = (struct stream_out *)stream;
2650
2651 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002652 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002653 out->offload_callback = callback;
2654 out->offload_cookie = cookie;
2655 pthread_mutex_unlock(&out->lock);
2656 return 0;
2657}
2658
2659static int out_pause(struct audio_stream_out* stream)
2660{
2661 struct stream_out *out = (struct stream_out *)stream;
2662 int status = -ENOSYS;
2663 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002664 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002665 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002666 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002667 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302668 struct audio_device *adev = out->dev;
2669 int snd_scard_state = get_snd_card_state(adev);
2670
2671 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2672 status = compress_pause(out->compr);
2673
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002675
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302676 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002677 audio_extn_dts_notify_playback_state(out->usecase, 0,
2678 out->sample_rate, popcount(out->channel_mask),
2679 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680 }
2681 pthread_mutex_unlock(&out->lock);
2682 }
2683 return status;
2684}
2685
2686static int out_resume(struct audio_stream_out* stream)
2687{
2688 struct stream_out *out = (struct stream_out *)stream;
2689 int status = -ENOSYS;
2690 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002691 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002692 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002693 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002694 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002695 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302696 struct audio_device *adev = out->dev;
2697 int snd_scard_state = get_snd_card_state(adev);
2698
2699 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2700 status = compress_resume(out->compr);
2701
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002702 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002703
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302704 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002705 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2706 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 }
2708 pthread_mutex_unlock(&out->lock);
2709 }
2710 return status;
2711}
2712
2713static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2714{
2715 struct stream_out *out = (struct stream_out *)stream;
2716 int status = -ENOSYS;
2717 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002718 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002719 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2721 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2722 else
2723 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2724 pthread_mutex_unlock(&out->lock);
2725 }
2726 return status;
2727}
2728
2729static int out_flush(struct audio_stream_out* stream)
2730{
2731 struct stream_out *out = (struct stream_out *)stream;
2732 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002733 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002734 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002735 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002736 stop_compressed_output_l(out);
2737 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002738 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002739 return 0;
2740 }
2741 return -ENOSYS;
2742}
2743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744/** audio_stream_in implementation **/
2745static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2746{
2747 struct stream_in *in = (struct stream_in *)stream;
2748
2749 return in->config.rate;
2750}
2751
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002752static int in_set_sample_rate(struct audio_stream *stream __unused,
2753 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754{
2755 return -ENOSYS;
2756}
2757
2758static size_t in_get_buffer_size(const struct audio_stream *stream)
2759{
2760 struct stream_in *in = (struct stream_in *)stream;
2761
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002762 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2763 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002764 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2765 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002766
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002767 return in->config.period_size *
2768 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769}
2770
2771static uint32_t in_get_channels(const struct audio_stream *stream)
2772{
2773 struct stream_in *in = (struct stream_in *)stream;
2774
2775 return in->channel_mask;
2776}
2777
2778static audio_format_t in_get_format(const struct audio_stream *stream)
2779{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002780 struct stream_in *in = (struct stream_in *)stream;
2781
2782 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783}
2784
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002785static int in_set_format(struct audio_stream *stream __unused,
2786 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787{
2788 return -ENOSYS;
2789}
2790
2791static int in_standby(struct audio_stream *stream)
2792{
2793 struct stream_in *in = (struct stream_in *)stream;
2794 struct audio_device *adev = in->dev;
2795 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302796 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2797 stream, in->usecase, use_case_table[in->usecase]);
2798
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002799 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2800 /* Ignore standby in case of voip call because the voip input
2801 * stream is closed in adev_close_input_stream()
2802 */
2803 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2804 return status;
2805 }
2806
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002807 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002808 if (!in->standby && in->is_st_session) {
2809 ALOGD("%s: sound trigger pcm stop lab", __func__);
2810 audio_extn_sound_trigger_stop_lab(in);
2811 in->standby = 1;
2812 }
2813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002815 if (adev->adm_deregister_stream)
2816 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2817
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002818 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002820 if (in->pcm) {
2821 pcm_close(in->pcm);
2822 in->pcm = NULL;
2823 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002825 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 }
2827 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002828 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 return status;
2830}
2831
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002832static int in_dump(const struct audio_stream *stream __unused,
2833 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834{
2835 return 0;
2836}
2837
2838static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2839{
2840 struct stream_in *in = (struct stream_in *)stream;
2841 struct audio_device *adev = in->dev;
2842 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002844 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302846 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 parms = str_parms_create_str(kvpairs);
2848
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302849 if (!parms)
2850 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002851 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002852 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002853
2854 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2855 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 val = atoi(value);
2857 /* no audio source uses val == 0 */
2858 if ((in->source != val) && (val != 0)) {
2859 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002860 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2861 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2862 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002863 (in->config.rate == 8000 || in->config.rate == 16000 ||
2864 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002865 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002866 err = voice_extn_compress_voip_open_input_stream(in);
2867 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002868 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002869 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002870 }
2871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872 }
2873 }
2874
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002875 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2876 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002878 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 in->device = val;
2880 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002881 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002882 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 }
2884 }
2885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002887 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888
2889 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302890error:
Eric Laurent994a6932013-07-17 11:51:42 -07002891 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 return ret;
2893}
2894
2895static char* in_get_parameters(const struct audio_stream *stream,
2896 const char *keys)
2897{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002898 struct stream_in *in = (struct stream_in *)stream;
2899 struct str_parms *query = str_parms_create_str(keys);
2900 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002901 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002902
2903 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002904 if (reply) {
2905 str_parms_destroy(reply);
2906 }
2907 if (query) {
2908 str_parms_destroy(query);
2909 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002910 ALOGE("in_get_parameters: failed to create query or reply");
2911 return NULL;
2912 }
2913
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002914 ALOGV("%s: enter: keys - %s", __func__, keys);
2915
2916 voice_extn_in_get_parameters(in, query, reply);
2917
2918 str = str_parms_to_str(reply);
2919 str_parms_destroy(query);
2920 str_parms_destroy(reply);
2921
2922 ALOGV("%s: exit: returns - %s", __func__, str);
2923 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924}
2925
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002926static int in_set_gain(struct audio_stream_in *stream __unused,
2927 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928{
2929 return 0;
2930}
2931
2932static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2933 size_t bytes)
2934{
2935 struct stream_in *in = (struct stream_in *)stream;
2936 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302937 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302938 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002940 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302941
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002942 if (in->is_st_session) {
2943 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2944 /* Read from sound trigger HAL */
2945 audio_extn_sound_trigger_read(in, buffer, bytes);
2946 pthread_mutex_unlock(&in->lock);
2947 return bytes;
2948 }
2949
Ashish Jainbbce4322016-02-16 13:25:27 +05302950 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002951 ALOGD(" %s: sound card is not active/SSR state", __func__);
2952 ret= -EIO;;
2953 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302954 }
2955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002957 pthread_mutex_lock(&adev->lock);
2958 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2959 ret = voice_extn_compress_voip_start_input_stream(in);
2960 else
2961 ret = start_input_stream(in);
2962 pthread_mutex_unlock(&adev->lock);
2963 if (ret != 0) {
2964 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 }
2966 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002967 if (adev->adm_register_input_stream)
2968 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002971 if (adev->adm_request_focus)
2972 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002975 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002976 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002977 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2978 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002979 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2980 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002981 else
2982 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302983 if (ret < 0)
2984 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 }
2986
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002987 if (adev->adm_abandon_focus)
2988 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 /*
2991 * Instead of writing zeroes here, we could trust the hardware
2992 * to always provide zeroes when muted.
2993 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302994 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2995 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 memset(buffer, 0, bytes);
2997
2998exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302999 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303000 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003001 if (-ENETRESET == ret)
3002 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 pthread_mutex_unlock(&in->lock);
3005
3006 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303007 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303008 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303009 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303010 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303011 in->standby = true;
3012 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303013 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003015 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303016 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303017 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 }
3019 return bytes;
3020}
3021
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003022static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023{
3024 return 0;
3025}
3026
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003027static int add_remove_audio_effect(const struct audio_stream *stream,
3028 effect_handle_t effect,
3029 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003031 struct stream_in *in = (struct stream_in *)stream;
3032 int status = 0;
3033 effect_descriptor_t desc;
3034
3035 status = (*effect)->get_descriptor(effect, &desc);
3036 if (status != 0)
3037 return status;
3038
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003039 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003040 pthread_mutex_lock(&in->dev->lock);
3041 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3042 in->enable_aec != enable &&
3043 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3044 in->enable_aec = enable;
3045 if (!in->standby)
3046 select_devices(in->dev, in->usecase);
3047 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003048 if (in->enable_ns != enable &&
3049 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3050 in->enable_ns = enable;
3051 if (!in->standby)
3052 select_devices(in->dev, in->usecase);
3053 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003054 pthread_mutex_unlock(&in->dev->lock);
3055 pthread_mutex_unlock(&in->lock);
3056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 return 0;
3058}
3059
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003060static int in_add_audio_effect(const struct audio_stream *stream,
3061 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062{
Eric Laurent994a6932013-07-17 11:51:42 -07003063 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003064 return add_remove_audio_effect(stream, effect, true);
3065}
3066
3067static int in_remove_audio_effect(const struct audio_stream *stream,
3068 effect_handle_t effect)
3069{
Eric Laurent994a6932013-07-17 11:51:42 -07003070 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003071 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072}
3073
3074static int adev_open_output_stream(struct audio_hw_device *dev,
3075 audio_io_handle_t handle,
3076 audio_devices_t devices,
3077 audio_output_flags_t flags,
3078 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003079 struct audio_stream_out **stream_out,
3080 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081{
3082 struct audio_device *adev = (struct audio_device *)dev;
3083 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303084 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003085 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303088
3089 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3090 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003091 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303092 return -EINVAL;
3093 }
3094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3096
Mingming Yin3a941d42016-02-17 18:08:05 -08003097 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3098 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303099 devices, flags, &out->stream);
3100
3101
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003102 if (!out) {
3103 return -ENOMEM;
3104 }
3105
Haynes Mathew George204045b2015-02-25 20:32:03 -08003106 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003107 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003108 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 if (devices == AUDIO_DEVICE_NONE)
3111 devices = AUDIO_DEVICE_OUT_SPEAKER;
3112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 out->flags = flags;
3114 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003115 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003116 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 out->sample_rate = config->sample_rate;
3118 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3119 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003120 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003121 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003122 out->non_blocking = 0;
3123 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124
Mingming Yin3a941d42016-02-17 18:08:05 -08003125 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3126 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3127 pthread_mutex_lock(&adev->lock);
3128 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3129 ret = read_hdmi_sink_caps(out);
3130 pthread_mutex_unlock(&adev->lock);
3131 if (ret != 0) {
3132 if (ret == -ENOSYS) {
3133 /* ignore and go with default */
3134 ret = 0;
3135 } else {
3136 ALOGE("error reading hdmi sink caps");
3137 goto error_open;
3138 }
3139 }
3140 }
3141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003143 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303144 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3145 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003146 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3147 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3148
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003149 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003150 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3151 /*
3152 * Do not handle stereo output in Multi-channel cases
3153 * Stereo case is handled in normal playback path
3154 */
3155 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3156 ret = AUDIO_CHANNEL_OUT_STEREO;
3157 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003158
3159 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3160 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003161 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003162 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003163 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003164
3165 if (config->sample_rate == 0)
3166 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3167 if (config->channel_mask == 0)
3168 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003169 if (config->format == 0)
3170 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003171
3172 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003173 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003174 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3176 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003180 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3181 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003182 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003183 ret = voice_extn_compress_voip_open_output_stream(out);
3184 if (ret != 0) {
3185 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3186 __func__, ret);
3187 goto error_open;
3188 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003189 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3190 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3191
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003192 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3193 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3194 ALOGE("%s: Unsupported Offload information", __func__);
3195 ret = -EINVAL;
3196 goto error_open;
3197 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003198
Mingming Yin3a941d42016-02-17 18:08:05 -08003199 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003200 if(config->offload_info.format == 0)
3201 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003202 if (config->offload_info.sample_rate == 0)
3203 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003204 }
3205
Mingming Yin90310102013-11-13 16:57:00 -08003206 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003207 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003208 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 ret = -EINVAL;
3210 goto error_open;
3211 }
3212
3213 out->compr_config.codec = (struct snd_codec *)
3214 calloc(1, sizeof(struct snd_codec));
3215
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003216 if (!out->compr_config.codec) {
3217 ret = -ENOMEM;
3218 goto error_open;
3219 }
3220
vivek mehta0ea887a2015-08-26 14:01:20 -07003221 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003222 out->usecase = get_offload_usecase(adev, true);
3223 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003224 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003225 out->stream.set_callback = out_set_callback;
3226 out->stream.pause = out_pause;
3227 out->stream.resume = out_resume;
3228 out->stream.drain = out_drain;
3229 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003230 out->usecase = get_offload_usecase(adev, false);
3231 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003232 }
vivek mehta446c3962015-09-14 10:57:35 -07003233
3234 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003235 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3236 config->format == 0 && config->sample_rate == 0 &&
3237 config->channel_mask == 0) {
3238 ALOGI("%s dummy open to query sink cap",__func__);
3239 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3240 } else {
3241 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3242 ret = -EEXIST;
3243 goto error_open;
3244 }
vivek mehta446c3962015-09-14 10:57:35 -07003245 }
3246
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003247 if (config->offload_info.channel_mask)
3248 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003249 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003250 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003251 config->offload_info.channel_mask = config->channel_mask;
3252 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003253 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003254 out->sample_rate = config->offload_info.sample_rate;
3255
Mingming Yin3ee55c62014-08-04 14:23:35 -07003256 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003258 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003259 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003260 audio_extn_dolby_get_snd_codec_id(adev, out,
3261 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003262 else
3263 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003265
3266 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3267 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003268 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003269 platform_get_pcm_offload_buffer_size(&config->offload_info);
3270 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3271 out->compr_config.fragment_size =
3272 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003273 } else {
3274 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003275 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003276 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003277 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3278 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003279 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280 out->compr_config.codec->bit_rate =
3281 config->offload_info.bit_rate;
3282 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003283 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003284 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303285 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003286 /*TODO: Do we need to change it for passthrough */
3287 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288
Manish Dewangana6fc5442015-08-24 20:30:31 +05303289 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3290 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3291 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3292 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003293 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3294 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003295 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003296 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003297 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3298 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003299
Mingming Yin3ee55c62014-08-04 14:23:35 -07003300 if (out->bit_width == 24) {
3301 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3302 }
3303
Amit Shekhar6f461b12014-08-01 14:52:58 -07003304 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303305 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3308 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003309
Mingming Yin497419f2015-07-01 16:57:32 -07003310 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003311 //this flag is set from framework only if its for PCM formats
3312 //no need to check for PCM format again
3313 out->non_blocking = 0;
3314 out->use_small_bufs = true;
3315 ALOGI("Keep write blocking for small buff: non_blockling %d",
3316 out->non_blocking);
3317 }
3318
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003319 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303320 out->send_next_track_params = false;
3321 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003322 out->offload_state = OFFLOAD_STATE_IDLE;
3323 out->playback_started = 0;
3324
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003325 audio_extn_dts_create_state_notifier_node(out->usecase);
3326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 create_offload_callback_thread(out);
3328 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3329 __func__, config->offload_info.version,
3330 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003331 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003332 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003333 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303334 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003335 if (ret != 0) {
3336 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3337 __func__, ret);
3338 goto error_open;
3339 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003340 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3341 if (config->sample_rate == 0)
3342 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3343 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3344 config->sample_rate != 8000) {
3345 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3346 ret = -EINVAL;
3347 goto error_open;
3348 }
3349 out->sample_rate = config->sample_rate;
3350 out->config.rate = config->sample_rate;
3351 if (config->format == AUDIO_FORMAT_DEFAULT)
3352 config->format = AUDIO_FORMAT_PCM_16_BIT;
3353 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3354 config->format = AUDIO_FORMAT_PCM_16_BIT;
3355 ret = -EINVAL;
3356 goto error_open;
3357 }
3358 out->format = config->format;
3359 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3360 out->config = pcm_config_afe_proxy_playback;
3361 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003362 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3363 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3364 out->config = pcm_config_low_latency;
3365 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003366 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003367 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3369 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003370 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003371 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3372 format = AUDIO_FORMAT_PCM_16_BIT;
3373 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3374 out->config = pcm_config_deep_buffer;
3375 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003376 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003377 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003378 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003379 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003380 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003381 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 }
3383
Amit Shekhar1d896042014-10-03 13:16:09 -07003384 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3385 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003386 /* TODO remove this hardcoding and check why width is zero*/
3387 if (out->bit_width == 0)
3388 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003389 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3390 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003391 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303392 out->bit_width, out->channel_mask,
3393 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003394 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3395 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3396 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003397 if(adev->primary_output == NULL)
3398 adev->primary_output = out;
3399 else {
3400 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003401 ret = -EEXIST;
3402 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003403 }
3404 }
3405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 /* Check if this usecase is already existing */
3407 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003408 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3409 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003412 ret = -EEXIST;
3413 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414 }
3415 pthread_mutex_unlock(&adev->lock);
3416
3417 out->stream.common.get_sample_rate = out_get_sample_rate;
3418 out->stream.common.set_sample_rate = out_set_sample_rate;
3419 out->stream.common.get_buffer_size = out_get_buffer_size;
3420 out->stream.common.get_channels = out_get_channels;
3421 out->stream.common.get_format = out_get_format;
3422 out->stream.common.set_format = out_set_format;
3423 out->stream.common.standby = out_standby;
3424 out->stream.common.dump = out_dump;
3425 out->stream.common.set_parameters = out_set_parameters;
3426 out->stream.common.get_parameters = out_get_parameters;
3427 out->stream.common.add_audio_effect = out_add_audio_effect;
3428 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3429 out->stream.get_latency = out_get_latency;
3430 out->stream.set_volume = out_set_volume;
3431 out->stream.write = out_write;
3432 out->stream.get_render_position = out_get_render_position;
3433 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003434 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003437 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003438 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439
3440 config->format = out->stream.common.get_format(&out->stream.common);
3441 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3442 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3443
3444 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303445 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003446 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003447
3448 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3449 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3450 popcount(out->channel_mask), out->playback_started);
3451
Eric Laurent994a6932013-07-17 11:51:42 -07003452 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003454
3455error_open:
3456 free(out);
3457 *stream_out = NULL;
3458 ALOGD("%s: exit: ret %d", __func__, ret);
3459 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460}
3461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003462static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 struct audio_stream_out *stream)
3464{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 struct stream_out *out = (struct stream_out *)stream;
3466 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003467 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303469 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3470
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003471 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303472 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003473 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303474 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003475 if(ret != 0)
3476 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3477 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003478 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003479 out_standby(&stream->common);
3480
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003481 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003482 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003484 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 if (out->compr_config.codec != NULL)
3486 free(out->compr_config.codec);
3487 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003488
3489 if (adev->voice_tx_output == out)
3490 adev->voice_tx_output = NULL;
3491
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492 pthread_cond_destroy(&out->cond);
3493 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003495 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496}
3497
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003498static void close_compress_sessions(struct audio_device *adev)
3499{
Mingming Yin7b762e72015-03-04 13:47:32 -08003500 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303501 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003502 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003503 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303504
3505 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003506 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303507 if (is_offload_usecase(usecase->id)) {
3508 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003509 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3510 out = usecase->stream.out;
3511 pthread_mutex_unlock(&adev->lock);
3512 out_standby(&out->stream.common);
3513 pthread_mutex_lock(&adev->lock);
3514 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303515 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003516 }
3517 pthread_mutex_unlock(&adev->lock);
3518}
3519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3521{
3522 struct audio_device *adev = (struct audio_device *)dev;
3523 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003525 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003526 int ret;
3527 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003529 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303532 if (!parms)
3533 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003534 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3535 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303536 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303537 if (strstr(snd_card_status, "OFFLINE")) {
3538 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303539 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003540 //close compress sessions on OFFLINE status
3541 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303542 } else if (strstr(snd_card_status, "ONLINE")) {
3543 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303544 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003545 //send dts hpx license if enabled
3546 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303547 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303548 }
3549
3550 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003551 status = voice_set_parameters(adev, parms);
3552 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003553 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003555 status = platform_set_parameters(adev->platform, parms);
3556 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003557 goto done;
3558
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003559 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3560 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003561 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3563 adev->bluetooth_nrec = true;
3564 else
3565 adev->bluetooth_nrec = false;
3566 }
3567
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003568 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3569 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3571 adev->screen_off = false;
3572 else
3573 adev->screen_off = true;
3574 }
3575
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003576 ret = str_parms_get_int(parms, "rotation", &val);
3577 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003578 bool reverse_speakers = false;
3579 switch(val) {
3580 // FIXME: note that the code below assumes that the speakers are in the correct placement
3581 // relative to the user when the device is rotated 90deg from its default rotation. This
3582 // assumption is device-specific, not platform-specific like this code.
3583 case 270:
3584 reverse_speakers = true;
3585 break;
3586 case 0:
3587 case 90:
3588 case 180:
3589 break;
3590 default:
3591 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003592 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003593 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003594 if (status == 0) {
3595 if (adev->speaker_lr_swap != reverse_speakers) {
3596 adev->speaker_lr_swap = reverse_speakers;
3597 // only update the selected device if there is active pcm playback
3598 struct audio_usecase *usecase;
3599 struct listnode *node;
3600 list_for_each(node, &adev->usecase_list) {
3601 usecase = node_to_item(node, struct audio_usecase, list);
3602 if (usecase->type == PCM_PLAYBACK) {
3603 select_devices(adev, usecase->id);
3604 break;
3605 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003606 }
3607 }
3608 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003609 }
3610
Mingming Yin514a8bc2014-07-29 15:22:21 -07003611 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3612 if (ret >= 0) {
3613 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3614 adev->bt_wb_speech_enabled = true;
3615 else
3616 adev->bt_wb_speech_enabled = false;
3617 }
3618
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003619 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3620 if (ret >= 0) {
3621 val = atoi(value);
3622 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3623 ALOGV("cache new edid");
3624 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003625 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3626 /*
3627 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3628 * Per AudioPolicyManager, USB device is higher priority than WFD.
3629 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3630 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3631 * starting voice call on USB
3632 */
3633 ALOGV("detected USB connect .. disable proxy");
3634 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003635 }
3636 }
3637
3638 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3639 if (ret >= 0) {
3640 val = atoi(value);
3641 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3642 ALOGV("invalidate cached edid");
3643 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003644 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3645 ALOGV("detected USB disconnect .. enable proxy");
3646 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003647 }
3648 }
3649
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003650 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003651
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003652done:
3653 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003654 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303655error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003656 ALOGV("%s: exit with code(%d)", __func__, status);
3657 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658}
3659
3660static char* adev_get_parameters(const struct audio_hw_device *dev,
3661 const char *keys)
3662{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003663 struct audio_device *adev = (struct audio_device *)dev;
3664 struct str_parms *reply = str_parms_create();
3665 struct str_parms *query = str_parms_create_str(keys);
3666 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303667 char value[256] = {0};
3668 int ret = 0;
3669
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003670 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003671 if (reply) {
3672 str_parms_destroy(reply);
3673 }
3674 if (query) {
3675 str_parms_destroy(query);
3676 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003677 ALOGE("adev_get_parameters: failed to create query or reply");
3678 return NULL;
3679 }
3680
Naresh Tannirud7205b62014-06-20 02:54:48 +05303681 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3682 sizeof(value));
3683 if (ret >=0) {
3684 int val = 1;
3685 pthread_mutex_lock(&adev->snd_card_status.lock);
3686 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3687 val = 0;
3688 pthread_mutex_unlock(&adev->snd_card_status.lock);
3689 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3690 goto exit;
3691 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003692
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003693 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003694 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003695 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003696 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303697 pthread_mutex_unlock(&adev->lock);
3698
Naresh Tannirud7205b62014-06-20 02:54:48 +05303699exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003700 str = str_parms_to_str(reply);
3701 str_parms_destroy(query);
3702 str_parms_destroy(reply);
3703
3704 ALOGV("%s: exit: returns - %s", __func__, str);
3705 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706}
3707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003708static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709{
3710 return 0;
3711}
3712
3713static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3714{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003715 int ret;
3716 struct audio_device *adev = (struct audio_device *)dev;
3717 pthread_mutex_lock(&adev->lock);
3718 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003719 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003720 pthread_mutex_unlock(&adev->lock);
3721 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722}
3723
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003724static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3725 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726{
3727 return -ENOSYS;
3728}
3729
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003730static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3731 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732{
3733 return -ENOSYS;
3734}
3735
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003736static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3737 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738{
3739 return -ENOSYS;
3740}
3741
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003742static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3743 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744{
3745 return -ENOSYS;
3746}
3747
3748static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3749{
3750 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 pthread_mutex_lock(&adev->lock);
3753 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003754 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003756 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003757 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003758 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003759 adev->current_call_output = NULL;
3760 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761 }
3762 pthread_mutex_unlock(&adev->lock);
3763 return 0;
3764}
3765
3766static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3767{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003768 int ret;
3769
3770 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003771 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003772 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3773 pthread_mutex_unlock(&adev->lock);
3774
3775 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776}
3777
3778static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3779{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003780 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 return 0;
3782}
3783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003784static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 const struct audio_config *config)
3786{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003787 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003789 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3790 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791}
3792
3793static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003794 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795 audio_devices_t devices,
3796 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003797 struct audio_stream_in **stream_in,
3798 audio_input_flags_t flags __unused,
3799 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003800 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801{
3802 struct audio_device *adev = (struct audio_device *)dev;
3803 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003804 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003805 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003806 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 *stream_in = NULL;
3809 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3810 return -EINVAL;
3811
3812 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003813
3814 if (!in) {
3815 ALOGE("failed to allocate input stream");
3816 return -ENOMEM;
3817 }
3818
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303819 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003820 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3821 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003823 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003824 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 in->stream.common.get_sample_rate = in_get_sample_rate;
3827 in->stream.common.set_sample_rate = in_set_sample_rate;
3828 in->stream.common.get_buffer_size = in_get_buffer_size;
3829 in->stream.common.get_channels = in_get_channels;
3830 in->stream.common.get_format = in_get_format;
3831 in->stream.common.set_format = in_set_format;
3832 in->stream.common.standby = in_standby;
3833 in->stream.common.dump = in_dump;
3834 in->stream.common.set_parameters = in_set_parameters;
3835 in->stream.common.get_parameters = in_get_parameters;
3836 in->stream.common.add_audio_effect = in_add_audio_effect;
3837 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3838 in->stream.set_gain = in_set_gain;
3839 in->stream.read = in_read;
3840 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3841
3842 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003843 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845 in->standby = 1;
3846 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003847 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003848 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849
3850 /* Update config params with the requested sample rate and channels */
3851 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003852 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3853 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3854 is_low_latency = true;
3855#if LOW_LATENCY_CAPTURE_USE_CASE
3856 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3857#endif
3858 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003861 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003863 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303864 if (adev->mode != AUDIO_MODE_IN_CALL) {
3865 ret = -EINVAL;
3866 goto err_open;
3867 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003868 if (config->sample_rate == 0)
3869 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3870 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3871 config->sample_rate != 8000) {
3872 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3873 ret = -EINVAL;
3874 goto err_open;
3875 }
3876 if (config->format == AUDIO_FORMAT_DEFAULT)
3877 config->format = AUDIO_FORMAT_PCM_16_BIT;
3878 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3879 config->format = AUDIO_FORMAT_PCM_16_BIT;
3880 ret = -EINVAL;
3881 goto err_open;
3882 }
3883
3884 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3885 in->config = pcm_config_afe_proxy_record;
3886 in->config.channels = channel_count;
3887 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303888 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3889 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003890 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003891 audio_extn_compr_cap_format_supported(config->format) &&
3892 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003893 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003894 } else {
3895 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003896 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003897 buffer_size = get_input_buffer_size(config->sample_rate,
3898 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003899 channel_count,
3900 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003901 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003902 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3903 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3904 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003905 (in->config.rate == 8000 || in->config.rate == 16000 ||
3906 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003907 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3908 voice_extn_compress_voip_open_input_stream(in);
3909 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003910 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003912 /* This stream could be for sound trigger lab,
3913 get sound trigger pcm if present */
3914 audio_extn_sound_trigger_check_and_get_session(in);
3915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003917 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003918 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919
3920err_open:
3921 free(in);
3922 *stream_in = NULL;
3923 return ret;
3924}
3925
3926static void adev_close_input_stream(struct audio_hw_device *dev,
3927 struct audio_stream_in *stream)
3928{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003929 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003930 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003931 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303932
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303933 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003934
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303935 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003936 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303937
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003938 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303939 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003940 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303941 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003942 if (ret != 0)
3943 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3944 __func__, ret);
3945 } else
3946 in_standby(&stream->common);
3947
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003948 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003949 audio_extn_ssr_deinit();
3950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951
Mingming Yine62d7842013-10-25 16:26:03 -07003952 if(audio_extn_compr_cap_enabled() &&
3953 audio_extn_compr_cap_format_supported(in->config.format))
3954 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003955
Mingming Yinfd7607b2016-01-22 12:48:44 -08003956 if (in->is_st_session) {
3957 ALOGV("%s: sound trigger pcm stop lab", __func__);
3958 audio_extn_sound_trigger_stop_lab(in);
3959 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003960 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 return;
3962}
3963
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003964static int adev_dump(const audio_hw_device_t *device __unused,
3965 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966{
3967 return 0;
3968}
3969
3970static int adev_close(hw_device_t *device)
3971{
3972 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003973
3974 if (!adev)
3975 return 0;
3976
3977 pthread_mutex_lock(&adev_init_lock);
3978
3979 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003980 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003981 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003982 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003983 audio_route_free(adev->audio_route);
3984 free(adev->snd_dev_ref_cnt);
3985 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003986 if (adev->adm_deinit)
3987 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003988 free(device);
3989 adev = NULL;
3990 }
3991 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993 return 0;
3994}
3995
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003996/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3997 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3998 * just that it _might_ work.
3999 */
4000static int period_size_is_plausible_for_low_latency(int period_size)
4001{
4002 switch (period_size) {
4003 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004004 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004005 case 240:
4006 case 320:
4007 case 480:
4008 return 1;
4009 default:
4010 return 0;
4011 }
4012}
4013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014static int adev_open(const hw_module_t *module, const char *name,
4015 hw_device_t **device)
4016{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004017 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4019
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004020 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004021 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004022 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004023 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004024 ALOGD("%s: returning existing instance of adev", __func__);
4025 ALOGD("%s: exit", __func__);
4026 pthread_mutex_unlock(&adev_init_lock);
4027 return 0;
4028 }
4029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030 adev = calloc(1, sizeof(struct audio_device));
4031
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004032 if (!adev) {
4033 pthread_mutex_unlock(&adev_init_lock);
4034 return -ENOMEM;
4035 }
4036
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004037 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4040 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4041 adev->device.common.module = (struct hw_module_t *)module;
4042 adev->device.common.close = adev_close;
4043
4044 adev->device.init_check = adev_init_check;
4045 adev->device.set_voice_volume = adev_set_voice_volume;
4046 adev->device.set_master_volume = adev_set_master_volume;
4047 adev->device.get_master_volume = adev_get_master_volume;
4048 adev->device.set_master_mute = adev_set_master_mute;
4049 adev->device.get_master_mute = adev_get_master_mute;
4050 adev->device.set_mode = adev_set_mode;
4051 adev->device.set_mic_mute = adev_set_mic_mute;
4052 adev->device.get_mic_mute = adev_get_mic_mute;
4053 adev->device.set_parameters = adev_set_parameters;
4054 adev->device.get_parameters = adev_get_parameters;
4055 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4056 adev->device.open_output_stream = adev_open_output_stream;
4057 adev->device.close_output_stream = adev_close_output_stream;
4058 adev->device.open_input_stream = adev_open_input_stream;
4059 adev->device.close_input_stream = adev_close_input_stream;
4060 adev->device.dump = adev_dump;
4061
4062 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004064 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004065 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004068 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004069 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004070 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004071 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004072 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004073 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004074 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004075 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304076 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304077 adev->perf_lock_opts[0] = 0x101;
4078 adev->perf_lock_opts[1] = 0x20E;
4079 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304080
4081 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4082 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004084 adev->platform = platform_init(adev);
4085 if (!adev->platform) {
4086 free(adev->snd_dev_ref_cnt);
4087 free(adev);
4088 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4089 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004090 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004091 return -EINVAL;
4092 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004093
Naresh Tanniru4c630392014-05-12 01:05:52 +05304094 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4095
Eric Laurentc4aef752013-09-12 17:45:53 -07004096 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4097 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4098 if (adev->visualizer_lib == NULL) {
4099 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4100 } else {
4101 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4102 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004103 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004104 "visualizer_hal_start_output");
4105 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004106 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004107 "visualizer_hal_stop_output");
4108 }
4109 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004110 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004111 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004112
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004113 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4114 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4115 if (adev->offload_effects_lib == NULL) {
4116 ALOGE("%s: DLOPEN failed for %s", __func__,
4117 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4118 } else {
4119 ALOGV("%s: DLOPEN successful for %s", __func__,
4120 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4121 adev->offload_effects_start_output =
4122 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4123 "offload_effects_bundle_hal_start_output");
4124 adev->offload_effects_stop_output =
4125 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4126 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004127 adev->offload_effects_set_hpx_state =
4128 (int (*)(bool))dlsym(adev->offload_effects_lib,
4129 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304130 adev->offload_effects_get_parameters =
4131 (void (*)(struct str_parms *, struct str_parms *))
4132 dlsym(adev->offload_effects_lib,
4133 "offload_effects_bundle_get_parameters");
4134 adev->offload_effects_set_parameters =
4135 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4136 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004137 }
4138 }
4139
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004140 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4141 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4142 if (adev->adm_lib == NULL) {
4143 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4144 } else {
4145 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4146 adev->adm_init = (adm_init_t)
4147 dlsym(adev->adm_lib, "adm_init");
4148 adev->adm_deinit = (adm_deinit_t)
4149 dlsym(adev->adm_lib, "adm_deinit");
4150 adev->adm_register_input_stream = (adm_register_input_stream_t)
4151 dlsym(adev->adm_lib, "adm_register_input_stream");
4152 adev->adm_register_output_stream = (adm_register_output_stream_t)
4153 dlsym(adev->adm_lib, "adm_register_output_stream");
4154 adev->adm_deregister_stream = (adm_deregister_stream_t)
4155 dlsym(adev->adm_lib, "adm_deregister_stream");
4156 adev->adm_request_focus = (adm_request_focus_t)
4157 dlsym(adev->adm_lib, "adm_request_focus");
4158 adev->adm_abandon_focus = (adm_abandon_focus_t)
4159 dlsym(adev->adm_lib, "adm_abandon_focus");
4160 }
4161 }
4162
Mingming Yin514a8bc2014-07-29 15:22:21 -07004163 adev->bt_wb_speech_enabled = false;
4164
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004165 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166 *device = &adev->device.common;
4167
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004168 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4169 &adev->streams_output_cfg_list);
4170
Kiran Kandi910e1862013-10-29 13:29:42 -07004171 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004172
4173 char value[PROPERTY_VALUE_MAX];
4174 int trial;
4175 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4176 trial = atoi(value);
4177 if (period_size_is_plausible_for_low_latency(trial)) {
4178 pcm_config_low_latency.period_size = trial;
4179 pcm_config_low_latency.start_threshold = trial / 4;
4180 pcm_config_low_latency.avail_min = trial / 4;
4181 configured_low_latency_capture_period_size = trial;
4182 }
4183 }
4184 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4185 trial = atoi(value);
4186 if (period_size_is_plausible_for_low_latency(trial)) {
4187 configured_low_latency_capture_period_size = trial;
4188 }
4189 }
4190
vivek mehta446c3962015-09-14 10:57:35 -07004191 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004192 pthread_mutex_unlock(&adev_init_lock);
4193
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004194 if (adev->adm_init)
4195 adev->adm_data = adev->adm_init();
4196
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304197 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004198 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 return 0;
4200}
4201
4202static struct hw_module_methods_t hal_module_methods = {
4203 .open = adev_open,
4204};
4205
4206struct audio_module HAL_MODULE_INFO_SYM = {
4207 .common = {
4208 .tag = HARDWARE_MODULE_TAG,
4209 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4210 .hal_api_version = HARDWARE_HAL_API_VERSION,
4211 .id = AUDIO_HARDWARE_MODULE_ID,
4212 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004213 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214 .methods = &hal_module_methods,
4215 },
4216};