blob: 7978adf9d17123bed6e49c2f8b62dac612a4a757 [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>
Ashish Jainf1eaa582016-05-23 20:54:24 +053067#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080068#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include "platform_api.h"
70#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070071#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080072#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080073
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080075#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053078/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
79#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080081#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
83
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070084#define PROXY_OPEN_RETRY_COUNT 100
85#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086
Mingming Yin08c7e312015-03-16 18:10:58 -070087#ifdef USE_LL_AS_PRIMARY_OUTPUT
88#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
89#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
90#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070092#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
93#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070095static unsigned int configured_low_latency_capture_period_size =
96 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
97
Eric Laurentb23d5282013-05-14 15:27:20 -070098struct pcm_config pcm_config_deep_buffer = {
99 .channels = 2,
100 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
101 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
102 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
103 .format = PCM_FORMAT_S16_LE,
104 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
105 .stop_threshold = INT_MAX,
106 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
107};
108
109struct pcm_config pcm_config_low_latency = {
110 .channels = 2,
111 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
112 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
113 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
114 .format = PCM_FORMAT_S16_LE,
115 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
116 .stop_threshold = INT_MAX,
117 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
118};
119
120struct pcm_config pcm_config_hdmi_multi = {
121 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
122 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
123 .period_size = HDMI_MULTI_PERIOD_SIZE,
124 .period_count = HDMI_MULTI_PERIOD_COUNT,
125 .format = PCM_FORMAT_S16_LE,
126 .start_threshold = 0,
127 .stop_threshold = INT_MAX,
128 .avail_min = 0,
129};
130
131struct pcm_config pcm_config_audio_capture = {
132 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700133 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
134 .format = PCM_FORMAT_S16_LE,
135};
136
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700137#define AFE_PROXY_CHANNEL_COUNT 2
138#define AFE_PROXY_SAMPLING_RATE 48000
139
140#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
141#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
142
143struct pcm_config pcm_config_afe_proxy_playback = {
144 .channels = AFE_PROXY_CHANNEL_COUNT,
145 .rate = AFE_PROXY_SAMPLING_RATE,
146 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
150 .stop_threshold = INT_MAX,
151 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
152};
153
154#define AFE_PROXY_RECORD_PERIOD_SIZE 768
155#define AFE_PROXY_RECORD_PERIOD_COUNT 4
156
157struct pcm_config pcm_config_afe_proxy_record = {
158 .channels = AFE_PROXY_CHANNEL_COUNT,
159 .rate = AFE_PROXY_SAMPLING_RATE,
160 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
164 .stop_threshold = INT_MAX,
165 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
166};
167
Ashish Jainf1eaa582016-05-23 20:54:24 +0530168#define AUDIO_MAX_PCM_FORMATS 7
169
170const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
171 [AUDIO_FORMAT_DEFAULT] = 0,
172 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
173 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
174 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
175 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
176 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
177 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
178};
179
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800180const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
182 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700183 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
184 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700185 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700186 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700187 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
188 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
189 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
190 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
191 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
192 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
193 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
194 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700195
Eric Laurentb23d5282013-05-14 15:27:20 -0700196 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700197 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700198 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700199 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700200 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800201 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800202 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700203 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700204
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700205 [USECASE_VOICE2_CALL] = "voice2-call",
206 [USECASE_VOLTE_CALL] = "volte-call",
207 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800208 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800209 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
210 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800211 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700212 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
213 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
214 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800215 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
216 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
217 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
218
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700219 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
220 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700221 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
222 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700223
224 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
225 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700226};
227
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700228static const audio_usecase_t offload_usecases[] = {
229 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700230 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
231 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
232 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
233 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
234 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
235 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
236 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
237 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700238};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239
240#define STRING_TO_ENUM(string) { #string, string }
241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800242struct string_to_enum {
243 const char *name;
244 uint32_t value;
245};
246
247static const struct string_to_enum out_channels_name_to_enum_table[] = {
248 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800249 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
250 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
251 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700252 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800253 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
254 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800255 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
256};
257
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700258static const struct string_to_enum out_formats_name_to_enum_table[] = {
259 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
260 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
261 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800262 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
263 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
264};
265
266//list of all supported sample rates by HDMI specification.
267static const int out_hdmi_sample_rates[] = {
268 32000, 44100, 48000, 88200, 96000, 176400, 192000,
269};
270
271static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
272 STRING_TO_ENUM(32000),
273 STRING_TO_ENUM(44100),
274 STRING_TO_ENUM(48000),
275 STRING_TO_ENUM(88200),
276 STRING_TO_ENUM(96000),
277 STRING_TO_ENUM(176400),
278 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700279};
280
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700281static struct audio_device *adev = NULL;
282static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700283static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700284//cache last MBDRC cal step level
285static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700286
vivek mehtaa76401a2015-04-24 14:12:15 -0700287__attribute__ ((visibility ("default")))
288bool audio_hw_send_gain_dep_calibration(int level) {
289 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700290 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700291
292 pthread_mutex_lock(&adev_init_lock);
293
294 if (adev != NULL && adev->platform != NULL) {
295 pthread_mutex_lock(&adev->lock);
296 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700297
298 // if cal set fails, cache level info
299 // if cal set succeds, reset known last cal set
300 if (!ret_val)
301 last_known_cal_step = level;
302 else if (last_known_cal_step != -1)
303 last_known_cal_step = -1;
304
vivek mehtaa76401a2015-04-24 14:12:15 -0700305 pthread_mutex_unlock(&adev->lock);
306 } else {
307 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
308 }
309
310 pthread_mutex_unlock(&adev_init_lock);
311
312 return ret_val;
313}
314
Ashish Jain5106d362016-05-11 19:23:33 +0530315static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
316{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800317 bool gapless_enabled = false;
318 const char *mixer_ctl_name = "Compress Gapless Playback";
319 struct mixer_ctl *ctl;
320
321 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530322 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
323
324 /*Disable gapless if its AV playback*/
325 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800326
327 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
328 if (!ctl) {
329 ALOGE("%s: Could not get ctl for mixer cmd - %s",
330 __func__, mixer_ctl_name);
331 return -EINVAL;
332 }
333
334 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
335 ALOGE("%s: Could not set gapless mode %d",
336 __func__, gapless_enabled);
337 return -EINVAL;
338 }
339 return 0;
340}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700341
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700342static bool is_supported_format(audio_format_t format)
343{
Eric Laurent86e17132013-09-12 17:49:30 -0700344 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530345 format == AUDIO_FORMAT_AAC_LC ||
346 format == AUDIO_FORMAT_AAC_HE_V1 ||
347 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530348 format == AUDIO_FORMAT_AAC_ADTS_LC ||
349 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
350 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530351 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
352 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530353 format == AUDIO_FORMAT_PCM_FLOAT ||
354 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700355 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530356 format == AUDIO_FORMAT_AC3 ||
357 format == AUDIO_FORMAT_E_AC3 ||
358 format == AUDIO_FORMAT_DTS ||
359 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800360 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530361 format == AUDIO_FORMAT_ALAC ||
362 format == AUDIO_FORMAT_APE ||
363 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800364 format == AUDIO_FORMAT_WMA ||
365 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800366 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700367
368 return false;
369}
370
371static int get_snd_codec_id(audio_format_t format)
372{
373 int id = 0;
374
Ashish Jainf9b78162014-08-25 20:36:25 +0530375 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700376 case AUDIO_FORMAT_MP3:
377 id = SND_AUDIOCODEC_MP3;
378 break;
379 case AUDIO_FORMAT_AAC:
380 id = SND_AUDIOCODEC_AAC;
381 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530382 case AUDIO_FORMAT_AAC_ADTS:
383 id = SND_AUDIOCODEC_AAC;
384 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700385 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800386 id = SND_AUDIOCODEC_PCM;
387 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700388 case AUDIO_FORMAT_FLAC:
389 id = SND_AUDIOCODEC_FLAC;
390 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530391 case AUDIO_FORMAT_ALAC:
392 id = SND_AUDIOCODEC_ALAC;
393 break;
394 case AUDIO_FORMAT_APE:
395 id = SND_AUDIOCODEC_APE;
396 break;
397 case AUDIO_FORMAT_VORBIS:
398 id = SND_AUDIOCODEC_VORBIS;
399 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800400 case AUDIO_FORMAT_WMA:
401 id = SND_AUDIOCODEC_WMA;
402 break;
403 case AUDIO_FORMAT_WMA_PRO:
404 id = SND_AUDIOCODEC_WMA_PRO;
405 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530406 case AUDIO_FORMAT_AC3:
407 id = SND_AUDIOCODEC_AC3;
408 break;
409 case AUDIO_FORMAT_E_AC3:
410 case AUDIO_FORMAT_E_AC3_JOC:
411 id = SND_AUDIOCODEC_EAC3;
412 break;
413 case AUDIO_FORMAT_DTS:
414 case AUDIO_FORMAT_DTS_HD:
415 id = SND_AUDIOCODEC_DTS;
416 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700417 default:
Mingming Yin90310102013-11-13 16:57:00 -0800418 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700419 }
420
421 return id;
422}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800423
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530424int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530425{
426 int snd_scard_state;
427
428 if (!adev)
429 return SND_CARD_STATE_OFFLINE;
430
431 pthread_mutex_lock(&adev->snd_card_status.lock);
432 snd_scard_state = adev->snd_card_status.state;
433 pthread_mutex_unlock(&adev->snd_card_status.lock);
434
435 return snd_scard_state;
436}
437
438static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
439{
440 if (!adev)
441 return -ENOSYS;
442
443 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700444 if (adev->snd_card_status.state != snd_scard_state) {
445 adev->snd_card_status.state = snd_scard_state;
446 platform_snd_card_update(adev->platform, snd_scard_state);
447 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530448 pthread_mutex_unlock(&adev->snd_card_status.lock);
449
450 return 0;
451}
452
Avinash Vaish71a8b972014-07-24 15:36:33 +0530453static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
454 struct audio_usecase *uc_info)
455{
456 struct listnode *node;
457 struct audio_usecase *usecase;
458
459 if (uc_info == NULL)
460 return -EINVAL;
461
462 /* Re-route all voice usecases on the shared backend other than the
463 specified usecase to new snd devices */
464 list_for_each(node, &adev->usecase_list) {
465 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800466 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530467 enable_audio_route(adev, usecase);
468 }
469 return 0;
470}
471
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700472int pcm_ioctl(struct pcm *pcm, int request, ...)
473{
474 va_list ap;
475 void * arg;
476 int pcm_fd = *(int*)pcm;
477
478 va_start(ap, request);
479 arg = va_arg(ap, void *);
480 va_end(ap);
481
482 return ioctl(pcm_fd, request, arg);
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700489 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800490
491 if (usecase == NULL)
492 return -EINVAL;
493
494 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
495
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800496 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700497 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800498 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700499 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800500
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800501#ifdef DS1_DOLBY_DAP_ENABLED
502 audio_extn_dolby_set_dmid(adev);
503 audio_extn_dolby_set_endpoint(adev);
504#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700505 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700506 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530507 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700508 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530509 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800510 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700511 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700512 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700513 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800514 ALOGV("%s: exit", __func__);
515 return 0;
516}
517
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700518int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700519 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700522 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800523
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530524 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800525 return -EINVAL;
526
527 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700528 if (usecase->type == PCM_CAPTURE)
529 snd_device = usecase->in_snd_device;
530 else
531 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800532 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700533 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700534 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700535 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530537 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800538 ALOGV("%s: exit", __func__);
539 return 0;
540}
541
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700542int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700543 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530545 int i, num_devices = 0;
546 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700547 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
548
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800549 if (snd_device < SND_DEVICE_MIN ||
550 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800551 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800552 return -EINVAL;
553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554
555 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700556
557 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
558 ALOGE("%s: Invalid sound device returned", __func__);
559 return -EINVAL;
560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700562 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700563 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 return 0;
565 }
566
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530567
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700568 if (audio_extn_spkr_prot_is_enabled())
569 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700570
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700571
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800572 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
573 audio_extn_spkr_prot_is_enabled()) {
574 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700575 adev->snd_dev_ref_cnt[snd_device]--;
576 return -EINVAL;
577 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200578 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800579 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800580 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200581 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 return -EINVAL;
583 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530584 } else if (platform_can_split_snd_device(adev->platform, snd_device,
585 &num_devices, new_snd_devices)) {
586 for (i = 0; i < num_devices; i++) {
587 enable_snd_device(adev, new_snd_devices[i]);
588 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800589 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700590 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700591 /* due to the possibility of calibration overwrite between listen
592 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700593 audio_extn_sound_trigger_update_device_status(snd_device,
594 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530595 audio_extn_listen_update_device_status(snd_device,
596 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700597 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700598 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700599 audio_extn_sound_trigger_update_device_status(snd_device,
600 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530601 audio_extn_listen_update_device_status(snd_device,
602 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700603 return -EINVAL;
604 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300605 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700606 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530607
608 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
609 !adev->native_playback_enabled &&
610 audio_is_true_native_stream_active(adev)) {
611 ALOGD("%s: %d: napb: enabling native mode in hardware",
612 __func__, __LINE__);
613 audio_route_apply_and_update_path(adev->audio_route,
614 "true-native-mode");
615 adev->native_playback_enabled = true;
616 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800618 return 0;
619}
620
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700621int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700622 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530624 int i, num_devices = 0;
625 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700626 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
627
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800628 if (snd_device < SND_DEVICE_MIN ||
629 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800630 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 return -EINVAL;
632 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
634 ALOGE("%s: device ref cnt is already 0", __func__);
635 return -EINVAL;
636 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700637
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700639
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700640 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
641 ALOGE("%s: Invalid sound device returned", __func__);
642 return -EINVAL;
643 }
644
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700646 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800647 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
648 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700649 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530650 } else if (platform_can_split_snd_device(adev->platform, snd_device,
651 &num_devices, new_snd_devices)) {
652 for (i = 0; i < num_devices; i++) {
653 disable_snd_device(adev, new_snd_devices[i]);
654 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300655 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700656 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300657 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700658
Ashish Jain81eb2a82015-05-13 10:52:34 +0530659 if (snd_device == SND_DEVICE_OUT_HDMI)
660 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530661 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
662 adev->native_playback_enabled) {
663 ALOGD("%s: %d: napb: disabling native mode in hardware",
664 __func__, __LINE__);
665 audio_route_reset_and_update_path(adev->audio_route,
666 "true-native-mode");
667 adev->native_playback_enabled = false;
668 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530669
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200670 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700671 audio_extn_sound_trigger_update_device_status(snd_device,
672 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530673 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800674 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677 return 0;
678}
679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530681 struct audio_usecase *uc_info,
682 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683{
684 struct listnode *node;
685 struct audio_usecase *usecase;
686 bool switch_device[AUDIO_USECASE_MAX];
687 int i, num_uc_to_switch = 0;
688
689 /*
690 * This function is to make sure that all the usecases that are active on
691 * the hardware codec backend are always routed to any one device that is
692 * handled by the hardware codec.
693 * For example, if low-latency and deep-buffer usecases are currently active
694 * on speaker and out_set_parameters(headset) is received on low-latency
695 * output, then we have to make sure deep-buffer is also switched to headset,
696 * because of the limitation that both the devices cannot be enabled
697 * at the same time as they share the same backend.
698 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700699 /*
700 * This call is to check if we need to force routing for a particular stream
701 * If there is a backend configuration change for the device when a
702 * new stream starts, then ADM needs to be closed and re-opened with the new
703 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800704 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700705 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800706 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
707 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530708
709 ALOGD("%s:becf: force routing %d", __func__, force_routing);
710
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800712 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800713 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700714 for (i = 0; i < AUDIO_USECASE_MAX; i++)
715 switch_device[i] = false;
716
717 list_for_each(node, &adev->usecase_list) {
718 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800719
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530720 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
721 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530722 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530723 platform_get_snd_device_name(usecase->out_snd_device),
724 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800725 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530726 usecase != uc_info &&
727 (usecase->out_snd_device != snd_device || force_routing) &&
728 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
729 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
730 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
731 __func__, use_case_table[usecase->id],
732 platform_get_snd_device_name(usecase->out_snd_device));
733 disable_audio_route(adev, usecase);
734 switch_device[usecase->id] = true;
735 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 }
737 }
738
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530739 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
740 num_uc_to_switch);
741
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530745 /* Make sure the previous devices to be disabled first and then enable the
746 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 list_for_each(node, &adev->usecase_list) {
748 usecase = node_to_item(node, struct audio_usecase, list);
749 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700750 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 }
752 }
753
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700754 list_for_each(node, &adev->usecase_list) {
755 usecase = node_to_item(node, struct audio_usecase, list);
756 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700757 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700758 }
759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 /* Re-route all the usecases on the shared backend other than the
762 specified usecase to new snd devices */
763 list_for_each(node, &adev->usecase_list) {
764 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530765 /* Update the out_snd_device only before enabling the audio route */
766 if (switch_device[usecase->id]) {
767 usecase->out_snd_device = snd_device;
768 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530769 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530770 use_case_table[usecase->id],
771 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530772 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530773 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700774 }
775 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700776 }
777}
778
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530779static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700780 struct audio_usecase *uc_info,
781 snd_device_t snd_device)
782{
783 struct listnode *node;
784 struct audio_usecase *usecase;
785 bool switch_device[AUDIO_USECASE_MAX];
786 int i, num_uc_to_switch = 0;
787
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530788 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
789 snd_device);
790 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700791 /*
792 * This function is to make sure that all the active capture usecases
793 * are always routed to the same input sound device.
794 * For example, if audio-record and voice-call usecases are currently
795 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
796 * is received for voice call then we have to make sure that audio-record
797 * usecase is also switched to earpiece i.e. voice-dmic-ef,
798 * because of the limitation that two devices cannot be enabled
799 * at the same time if they share the same backend.
800 */
801 for (i = 0; i < AUDIO_USECASE_MAX; i++)
802 switch_device[i] = false;
803
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800806 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530808 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700809 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530810 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
811 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700812 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700813 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
814 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700815 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700816 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700817 switch_device[usecase->id] = true;
818 num_uc_to_switch++;
819 }
820 }
821
822 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700823 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700824
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530825 /* Make sure the previous devices to be disabled first and then enable the
826 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700827 list_for_each(node, &adev->usecase_list) {
828 usecase = node_to_item(node, struct audio_usecase, list);
829 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700830 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800831 }
832 }
833
834 list_for_each(node, &adev->usecase_list) {
835 usecase = node_to_item(node, struct audio_usecase, list);
836 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700837 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700838 }
839 }
840
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700841 /* Re-route all the usecases on the shared backend other than the
842 specified usecase to new snd devices */
843 list_for_each(node, &adev->usecase_list) {
844 usecase = node_to_item(node, struct audio_usecase, list);
845 /* Update the in_snd_device only before enabling the audio route */
846 if (switch_device[usecase->id] ) {
847 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800848 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530849 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700850 }
851 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700852 }
853}
854
Mingming Yin3a941d42016-02-17 18:08:05 -0800855static void reset_hdmi_sink_caps(struct stream_out *out) {
856 int i = 0;
857
858 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
859 out->supported_channel_masks[i] = 0;
860 }
861 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
862 out->supported_formats[i] = 0;
863 }
864 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
865 out->supported_sample_rates[i] = 0;
866 }
867}
868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800869/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800870static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871{
Mingming Yin3a941d42016-02-17 18:08:05 -0800872 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700873 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874
Mingming Yin3a941d42016-02-17 18:08:05 -0800875 reset_hdmi_sink_caps(out);
876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800879 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700880 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800881 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
882 case 6:
883 ALOGV("%s: HDMI supports 5.1 channels", __func__);
884 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
885 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
886 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
887 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
888 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800889 break;
890 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800891 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700892 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800893 break;
894 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800895
896 // check channel format caps
897 i = 0;
898 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
899 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
900 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
901 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
902 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
903 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
904 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
905 }
906
907 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
908 ALOGV(":%s HDMI supports DTS format", __func__);
909 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
910 }
911
912 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
913 ALOGV(":%s HDMI supports DTS HD format", __func__);
914 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
915 }
916
917
918 // check sample rate caps
919 i = 0;
920 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
921 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
922 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
923 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
924 }
925 }
926
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700927 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928}
929
Alexy Josephb1379942016-01-29 15:49:38 -0800930audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800931 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700932{
933 struct audio_usecase *usecase;
934 struct listnode *node;
935
936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800938 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700939 ALOGV("%s: usecase id %d", __func__, usecase->id);
940 return usecase->id;
941 }
942 }
943 return USECASE_INVALID;
944}
945
Alexy Josephb1379942016-01-29 15:49:38 -0800946struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700947 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948{
949 struct audio_usecase *usecase;
950 struct listnode *node;
951
952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (usecase->id == uc_id)
955 return usecase;
956 }
957 return NULL;
958}
959
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530960/*
961 * is a true native playback active
962 */
963bool audio_is_true_native_stream_active(struct audio_device *adev)
964{
965 bool active = false;
966 int i = 0;
967 struct listnode *node;
968
969 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
970 ALOGV("%s:napb: not in true mode or non hdphones device",
971 __func__);
972 active = false;
973 goto exit;
974 }
975
976 list_for_each(node, &adev->usecase_list) {
977 struct audio_usecase *uc;
978 uc = node_to_item(node, struct audio_usecase, list);
979 struct stream_out *curr_out =
980 (struct stream_out*) uc->stream.out;
981
982 if (curr_out && PCM_PLAYBACK == uc->type) {
983 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
984 "(%d) device %s", __func__, i++, use_case_table[uc->id],
985 uc->id, curr_out->sample_rate,
986 curr_out->bit_width,
987 platform_get_snd_device_name(uc->out_snd_device));
988
989 if (is_offload_usecase(uc->id) &&
990 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
991 active = true;
992 ALOGD("%s:napb:native stream detected", __func__);
993 }
994 }
995 }
996exit:
997 return active;
998}
999
1000
1001static bool force_device_switch(struct audio_usecase *usecase)
1002{
1003 bool ret = false;
1004 bool is_it_true_mode = false;
1005
1006 if (is_offload_usecase(usecase->id) &&
1007 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001008 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1009 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1010 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301011 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1012 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1013 (!is_it_true_mode && adev->native_playback_enabled)){
1014 ret = true;
1015 ALOGD("napb: time to toggle native mode");
1016 }
1017 }
1018
1019 return ret;
1020}
1021
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001022int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001024 snd_device_t out_snd_device = SND_DEVICE_NONE;
1025 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 struct audio_usecase *usecase = NULL;
1027 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001028 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001029 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001030 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301033 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1034
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035 usecase = get_usecase_from_list(adev, uc_id);
1036 if (usecase == NULL) {
1037 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1038 return -EINVAL;
1039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001041 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001042 (usecase->type == VOIP_CALL) ||
1043 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001044 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001045 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001046 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 usecase->devices = usecase->stream.out->devices;
1048 } else {
1049 /*
1050 * If the voice call is active, use the sound devices of voice call usecase
1051 * so that it would not result any device switch. All the usecases will
1052 * be switched to new device when select_devices() is called for voice call
1053 * usecase. This is to avoid switching devices for voice call when
1054 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001055 * choose voice call device only if the use case device is
1056 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001058 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001059 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001060 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001061 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1062 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1063 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001064 in_snd_device = vc_usecase->in_snd_device;
1065 out_snd_device = vc_usecase->out_snd_device;
1066 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001067 } else if (voice_extn_compress_voip_is_active(adev)) {
1068 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001069 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301070 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001071 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001072 in_snd_device = voip_usecase->in_snd_device;
1073 out_snd_device = voip_usecase->out_snd_device;
1074 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001075 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001076 hfp_ucid = audio_extn_hfp_get_usecase();
1077 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001078 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001079 in_snd_device = hfp_usecase->in_snd_device;
1080 out_snd_device = hfp_usecase->out_snd_device;
1081 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 }
1083 if (usecase->type == PCM_PLAYBACK) {
1084 usecase->devices = usecase->stream.out->devices;
1085 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001086 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001087 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001088 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001089 if (usecase->stream.out == adev->primary_output &&
1090 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001091 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001092 select_devices(adev, adev->active_input->usecase);
1093 }
1094 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 } else if (usecase->type == PCM_CAPTURE) {
1096 usecase->devices = usecase->stream.in->device;
1097 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001098 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001099 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001100 if (adev->active_input &&
1101 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301102 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1103 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1104 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001105 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001106 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001107 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1108 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001109 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001110 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 }
1113 }
1114
1115 if (out_snd_device == usecase->out_snd_device &&
1116 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301117
1118 if (!force_device_switch(usecase))
1119 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 }
1121
sangwoobc677242013-08-08 16:53:43 +09001122 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001123 out_snd_device, platform_get_snd_device_name(out_snd_device),
1124 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 /*
1127 * Limitation: While in call, to do a device switch we need to disable
1128 * and enable both RX and TX devices though one of them is same as current
1129 * device.
1130 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001131 if ((usecase->type == VOICE_CALL) &&
1132 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1133 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001134 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001135 }
1136
1137 if (((usecase->type == VOICE_CALL) ||
1138 (usecase->type == VOIP_CALL)) &&
1139 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1140 /* Disable sidetone only if voice/voip call already exists */
1141 if (voice_is_call_state_active(adev) ||
1142 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001143 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001144 }
1145
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 /* Disable current sound devices */
1147 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001148 disable_audio_route(adev, usecase);
1149 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 }
1151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001153 disable_audio_route(adev, usecase);
1154 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 }
1156
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001157 /* Applicable only on the targets that has external modem.
1158 * New device information should be sent to modem before enabling
1159 * the devices to reduce in-call device switch time.
1160 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001161 if ((usecase->type == VOICE_CALL) &&
1162 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1163 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001164 status = platform_switch_voice_call_enable_device_config(adev->platform,
1165 out_snd_device,
1166 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001167 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 /* Enable new sound devices */
1170 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001171 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001172 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 }
1174
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301176 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001177 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179
Avinash Vaish71a8b972014-07-24 15:36:33 +05301180 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001181 status = platform_switch_voice_call_device_post(adev->platform,
1182 out_snd_device,
1183 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301184 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001185 /* Enable sidetone only if voice/voip call already exists */
1186 if (voice_is_call_state_active(adev) ||
1187 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001188 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301189 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001190
sangwoo170731f2013-06-08 15:36:36 +09001191 usecase->in_snd_device = in_snd_device;
1192 usecase->out_snd_device = out_snd_device;
1193
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301194 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001195 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301196 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001197 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301198 usecase->stream.out->flags,
1199 usecase->stream.out->format,
1200 usecase->stream.out->sample_rate,
1201 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301202 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301203 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001204 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301205 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001206
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001207 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001208
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001209 /* Applicable only on the targets that has external modem.
1210 * Enable device command should be sent to modem only after
1211 * enabling voice call mixer controls
1212 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001213 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001214 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1215 out_snd_device,
1216 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301217 ALOGD("%s: done",__func__);
1218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219 return status;
1220}
1221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222static int stop_input_stream(struct stream_in *in)
1223{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301224 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 struct audio_usecase *uc_info;
1226 struct audio_device *adev = in->dev;
1227
Eric Laurentc8400632013-02-14 19:04:54 -08001228 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Eric Laurent994a6932013-07-17 11:51:42 -07001230 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 uc_info = get_usecase_from_list(adev, in->usecase);
1233 if (uc_info == NULL) {
1234 ALOGE("%s: Could not find the usecase (%d) in the list",
1235 __func__, in->usecase);
1236 return -EINVAL;
1237 }
1238
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001239 /* Close in-call recording streams */
1240 voice_check_and_stop_incall_rec_usecase(adev, in);
1241
Eric Laurent150dbfe2013-02-27 14:31:02 -08001242 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001243 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244
1245 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001246 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001248 list_remove(&uc_info->list);
1249 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250
Eric Laurent994a6932013-07-17 11:51:42 -07001251 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 return ret;
1253}
1254
1255int start_input_stream(struct stream_in *in)
1256{
1257 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001258 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 struct audio_usecase *uc_info;
1260 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301261 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262
Mingming Yin2664a5b2015-09-03 10:53:11 -07001263 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1264 if (get_usecase_from_list(adev, usecase) == NULL)
1265 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301266 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1267 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001268
Naresh Tanniru80659832014-06-04 18:17:56 +05301269
1270 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301271 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301272 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301273 goto error_config;
1274 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301275
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001276 /* Check if source matches incall recording usecase criteria */
1277 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1278 if (ret)
1279 goto error_config;
1280 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001281 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1282
1283 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1284 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1285 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001286 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001287 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001288
Eric Laurentb23d5282013-05-14 15:27:20 -07001289 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 if (in->pcm_device_id < 0) {
1291 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1292 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001293 ret = -EINVAL;
1294 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296
1297 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001299
1300 if (!uc_info) {
1301 ret = -ENOMEM;
1302 goto error_config;
1303 }
1304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305 uc_info->id = in->usecase;
1306 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001307 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 uc_info->devices = in->device;
1309 uc_info->in_snd_device = SND_DEVICE_NONE;
1310 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001312 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301313 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1314 adev->perf_lock_opts,
1315 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301318 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1319 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001320
1321 unsigned int flags = PCM_IN;
1322 unsigned int pcm_open_retry_count = 0;
1323
1324 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1325 flags |= PCM_MMAP | PCM_NOIRQ;
1326 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1327 }
1328
1329 while (1) {
1330 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1331 flags, &in->config);
1332 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1333 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1334 if (in->pcm != NULL) {
1335 pcm_close(in->pcm);
1336 in->pcm = NULL;
1337 }
1338 if (pcm_open_retry_count-- == 0) {
1339 ret = -EIO;
1340 goto error_open;
1341 }
1342 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1343 continue;
1344 }
1345 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001347
1348 ALOGV("%s: pcm_prepare", __func__);
1349 ret = pcm_prepare(in->pcm);
1350 if (ret < 0) {
1351 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1352 pcm_close(in->pcm);
1353 in->pcm = NULL;
1354 goto error_open;
1355 }
1356
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301357 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001358 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001359
Eric Laurentc8400632013-02-14 19:04:54 -08001360 return ret;
1361
1362error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301363 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001365error_config:
1366 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301367 /*
1368 * sleep 50ms to allow sufficient time for kernel
1369 * drivers to recover incases like SSR.
1370 */
1371 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001373
1374 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375}
1376
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001377void lock_input_stream(struct stream_in *in)
1378{
1379 pthread_mutex_lock(&in->pre_lock);
1380 pthread_mutex_lock(&in->lock);
1381 pthread_mutex_unlock(&in->pre_lock);
1382}
1383
1384void lock_output_stream(struct stream_out *out)
1385{
1386 pthread_mutex_lock(&out->pre_lock);
1387 pthread_mutex_lock(&out->lock);
1388 pthread_mutex_unlock(&out->pre_lock);
1389}
1390
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001391/* must be called with out->lock locked */
1392static int send_offload_cmd_l(struct stream_out* out, int command)
1393{
1394 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1395
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001396 if (!cmd) {
1397 ALOGE("failed to allocate mem for command 0x%x", command);
1398 return -ENOMEM;
1399 }
1400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001401 ALOGVV("%s %d", __func__, command);
1402
1403 cmd->cmd = command;
1404 list_add_tail(&out->offload_cmd_list, &cmd->node);
1405 pthread_cond_signal(&out->offload_cond);
1406 return 0;
1407}
1408
1409/* must be called iwth out->lock locked */
1410static void stop_compressed_output_l(struct stream_out *out)
1411{
1412 out->offload_state = OFFLOAD_STATE_IDLE;
1413 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001414 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001415 if (out->compr != NULL) {
1416 compress_stop(out->compr);
1417 while (out->offload_thread_blocked) {
1418 pthread_cond_wait(&out->cond, &out->lock);
1419 }
1420 }
1421}
1422
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001423bool is_offload_usecase(audio_usecase_t uc_id)
1424{
1425 unsigned int i;
1426 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1427 if (uc_id == offload_usecases[i])
1428 return true;
1429 }
1430 return false;
1431}
1432
vivek mehta446c3962015-09-14 10:57:35 -07001433static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001434{
vivek mehta446c3962015-09-14 10:57:35 -07001435 audio_usecase_t ret_uc = USECASE_INVALID;
1436 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001437 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001438 if (!adev->multi_offload_enable) {
1439 if (is_direct_pcm)
1440 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1441 else
1442 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001443
vivek mehta446c3962015-09-14 10:57:35 -07001444 pthread_mutex_lock(&adev->lock);
1445 if (get_usecase_from_list(adev, ret_uc) != NULL)
1446 ret_uc = USECASE_INVALID;
1447 pthread_mutex_unlock(&adev->lock);
1448
1449 return ret_uc;
1450 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001451
1452 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001453 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1454 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1455 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1456 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001457 break;
1458 }
1459 }
vivek mehta446c3962015-09-14 10:57:35 -07001460
1461 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1462 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001463}
1464
1465static void free_offload_usecase(struct audio_device *adev,
1466 audio_usecase_t uc_id)
1467{
vivek mehta446c3962015-09-14 10:57:35 -07001468 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001469 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001470
1471 if (!adev->multi_offload_enable)
1472 return;
1473
1474 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1475 if (offload_usecases[offload_uc_index] == uc_id) {
1476 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001477 break;
1478 }
1479 }
1480 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1481}
1482
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483static void *offload_thread_loop(void *context)
1484{
1485 struct stream_out *out = (struct stream_out *) context;
1486 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001487 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001489 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1490 set_sched_policy(0, SP_FOREGROUND);
1491 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1492
1493 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001494 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001495 for (;;) {
1496 struct offload_cmd *cmd = NULL;
1497 stream_callback_event_t event;
1498 bool send_callback = false;
1499
1500 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1501 __func__, list_empty(&out->offload_cmd_list),
1502 out->offload_state);
1503 if (list_empty(&out->offload_cmd_list)) {
1504 ALOGV("%s SLEEPING", __func__);
1505 pthread_cond_wait(&out->offload_cond, &out->lock);
1506 ALOGV("%s RUNNING", __func__);
1507 continue;
1508 }
1509
1510 item = list_head(&out->offload_cmd_list);
1511 cmd = node_to_item(item, struct offload_cmd, node);
1512 list_remove(item);
1513
1514 ALOGVV("%s STATE %d CMD %d out->compr %p",
1515 __func__, out->offload_state, cmd->cmd, out->compr);
1516
1517 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1518 free(cmd);
1519 break;
1520 }
1521
1522 if (out->compr == NULL) {
1523 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001524 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001525 pthread_cond_signal(&out->cond);
1526 continue;
1527 }
1528 out->offload_thread_blocked = true;
1529 pthread_mutex_unlock(&out->lock);
1530 send_callback = false;
1531 switch(cmd->cmd) {
1532 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001533 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001535 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001536 send_callback = true;
1537 event = STREAM_CBK_EVENT_WRITE_READY;
1538 break;
1539 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001540 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301541 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001542 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301543 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001544 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301545 if (ret < 0)
1546 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301547 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301548 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001549 compress_drain(out->compr);
1550 else
1551 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301552 if (ret != -ENETRESET) {
1553 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301554 pthread_mutex_lock(&out->lock);
1555 out->send_new_metadata = 1;
1556 out->send_next_track_params = true;
1557 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301558 event = STREAM_CBK_EVENT_DRAIN_READY;
1559 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1560 } else
1561 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001562 break;
1563 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001564 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001565 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001566 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001567 send_callback = true;
1568 event = STREAM_CBK_EVENT_DRAIN_READY;
1569 break;
1570 default:
1571 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1572 break;
1573 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001574 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001575 out->offload_thread_blocked = false;
1576 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001577 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001578 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001579 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001580 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 free(cmd);
1582 }
1583
1584 pthread_cond_signal(&out->cond);
1585 while (!list_empty(&out->offload_cmd_list)) {
1586 item = list_head(&out->offload_cmd_list);
1587 list_remove(item);
1588 free(node_to_item(item, struct offload_cmd, node));
1589 }
1590 pthread_mutex_unlock(&out->lock);
1591
1592 return NULL;
1593}
1594
1595static int create_offload_callback_thread(struct stream_out *out)
1596{
1597 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1598 list_init(&out->offload_cmd_list);
1599 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1600 offload_thread_loop, out);
1601 return 0;
1602}
1603
1604static int destroy_offload_callback_thread(struct stream_out *out)
1605{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001606 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 stop_compressed_output_l(out);
1608 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1609
1610 pthread_mutex_unlock(&out->lock);
1611 pthread_join(out->offload_thread, (void **) NULL);
1612 pthread_cond_destroy(&out->offload_cond);
1613
1614 return 0;
1615}
1616
Mingming Yin21854652016-04-13 11:54:02 -07001617static bool allow_hdmi_channel_config(struct audio_device *adev,
1618 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001619{
1620 struct listnode *node;
1621 struct audio_usecase *usecase;
1622 bool ret = true;
1623
Mingming Yin21854652016-04-13 11:54:02 -07001624 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1625 ret = false;
1626 goto exit;
1627 }
1628
1629 if (audio_extn_passthru_is_active()) {
1630 ALOGI("%s: Compress audio passthrough is active,"
1631 "no HDMI config change allowed", __func__);
1632 ret = false;
1633 goto exit;
1634 }
1635
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 list_for_each(node, &adev->usecase_list) {
1637 usecase = node_to_item(node, struct audio_usecase, list);
1638 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1639 /*
1640 * If voice call is already existing, do not proceed further to avoid
1641 * disabling/enabling both RX and TX devices, CSD calls, etc.
1642 * Once the voice call done, the HDMI channels can be configured to
1643 * max channels of remaining use cases.
1644 */
1645 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001646 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001647 __func__);
1648 ret = false;
1649 break;
1650 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001651 if (!enable_passthru) {
1652 ALOGV("%s: multi channel playback is active, "
1653 "no change in HDMI channels", __func__);
1654 ret = false;
1655 break;
1656 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001657 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001658 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001659 if (!enable_passthru) {
1660 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1661 ", no change in HDMI channels", __func__,
1662 usecase->stream.out->channel_mask);
1663 ret = false;
1664 break;
1665 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001666 }
1667 }
1668 }
Mingming Yin21854652016-04-13 11:54:02 -07001669 ALOGV("allow hdmi config %d", ret);
1670exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001671 return ret;
1672}
1673
Mingming Yin21854652016-04-13 11:54:02 -07001674static int check_and_set_hdmi_config(struct audio_device *adev,
1675 uint32_t channels,
1676 uint32_t sample_rate,
1677 audio_format_t format,
1678 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001679{
1680 struct listnode *node;
1681 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001682 int32_t factor = 1;
1683 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001684
Mingming Yin21854652016-04-13 11:54:02 -07001685 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1686 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001687
Mingming Yin21854652016-04-13 11:54:02 -07001688 if (channels != adev->cur_hdmi_channels) {
1689 ALOGV("channel does not match current hdmi channels");
1690 config = true;
1691 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001692
Mingming Yin21854652016-04-13 11:54:02 -07001693 if (sample_rate != adev->cur_hdmi_sample_rate) {
1694 ALOGV("sample rate does not match current hdmi sample rate");
1695 config = true;
1696 }
1697
1698 if (format != adev->cur_hdmi_format) {
1699 ALOGV("format does not match current hdmi format");
1700 config = true;
1701 }
1702
1703 /* TBD - add check for bit width */
1704 if (!config) {
1705 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001706 return 0;
1707 }
1708
Mingming Yin21854652016-04-13 11:54:02 -07001709 if (enable_passthru &&
1710 (format == AUDIO_FORMAT_E_AC3)) {
1711 ALOGV("factor 4 for E_AC3 passthru");
1712 factor = 4;
1713 }
1714
1715 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1716 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001717 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001718 adev->cur_hdmi_format = format;
1719 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001720
1721 /*
1722 * Deroute all the playback streams routed to HDMI so that
1723 * the back end is deactivated. Note that backend will not
1724 * be deactivated if any one stream is connected to it.
1725 */
1726 list_for_each(node, &adev->usecase_list) {
1727 usecase = node_to_item(node, struct audio_usecase, list);
1728 if (usecase->type == PCM_PLAYBACK &&
1729 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001730 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001731 }
1732 }
1733
Mingming Yin21854652016-04-13 11:54:02 -07001734 bool was_active = audio_extn_keep_alive_is_active();
1735 if (was_active)
1736 audio_extn_keep_alive_stop();
1737
Eric Laurent07eeafd2013-10-06 12:52:49 -07001738 /*
1739 * Enable all the streams disabled above. Now the HDMI backend
1740 * will be activated with new channel configuration
1741 */
1742 list_for_each(node, &adev->usecase_list) {
1743 usecase = node_to_item(node, struct audio_usecase, list);
1744 if (usecase->type == PCM_PLAYBACK &&
1745 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001746 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001747 }
1748 }
1749
Mingming Yin21854652016-04-13 11:54:02 -07001750 if (was_active)
1751 audio_extn_keep_alive_start();
1752
Eric Laurent07eeafd2013-10-06 12:52:49 -07001753 return 0;
1754}
1755
Mingming Yin21854652016-04-13 11:54:02 -07001756/* called with out lock taken */
1757static int check_and_set_hdmi_backend(struct stream_out *out)
1758{
1759 struct audio_device *adev = out->dev;
1760 int ret;
1761 bool enable_passthru = false;
1762
1763 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1764 return -1;
1765
1766 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1767
1768 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301769 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001770 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301771 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001772 }
1773
1774 /* Check if change in HDMI channel config is allowed */
1775 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1776 return -EPERM;
1777 }
1778
1779 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1780 uint32_t channels;
1781 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1782
1783 if (enable_passthru) {
1784 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301785 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001786 }
1787
1788 /* For pass through case, the backend should be configured as stereo */
1789 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1790 out->compr_config.codec->ch_in;
1791
1792 ret = check_and_set_hdmi_config(adev, channels,
1793 out->sample_rate, out->format,
1794 enable_passthru);
1795 } else
1796 ret = check_and_set_hdmi_config(adev, out->config.channels,
1797 out->config.rate,
1798 out->format,
1799 false);
1800 return ret;
1801}
1802
1803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804static int stop_output_stream(struct stream_out *out)
1805{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301806 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 struct audio_usecase *uc_info;
1808 struct audio_device *adev = out->dev;
1809
Eric Laurent994a6932013-07-17 11:51:42 -07001810 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 uc_info = get_usecase_from_list(adev, out->usecase);
1813 if (uc_info == NULL) {
1814 ALOGE("%s: Could not find the usecase (%d) in the list",
1815 __func__, out->usecase);
1816 return -EINVAL;
1817 }
1818
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001819 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301820 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001821 if (adev->visualizer_stop_output != NULL)
1822 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001823
1824 audio_extn_dts_remove_state_notifier_node(out->usecase);
1825
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001826 if (adev->offload_effects_stop_output != NULL)
1827 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1828 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001829
Eric Laurent150dbfe2013-02-27 14:31:02 -08001830 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001831 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832
1833 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001834 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001836 list_remove(&uc_info->list);
1837 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001839 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301840 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001841 ALOGV("Disable passthrough , reset mixer to pcm");
1842 /* NO_PASSTHROUGH */
1843 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001844
Mingming Yin21854652016-04-13 11:54:02 -07001845 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001846 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1847 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001848
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301849 /* Must be called after removing the usecase from list */
1850 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1851 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1852 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1853 DEFAULT_HDMI_OUT_FORMAT,
1854 false);
Eric Laurent994a6932013-07-17 11:51:42 -07001855 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 return ret;
1857}
1858
1859int start_output_stream(struct stream_out *out)
1860{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 struct audio_usecase *uc_info;
1863 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301864 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001866 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1867 ret = -EINVAL;
1868 goto error_config;
1869 }
1870
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301871 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1872 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1873 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301874
Naresh Tanniru80659832014-06-04 18:17:56 +05301875 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301876 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301877 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301878 goto error_config;
1879 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301880
Eric Laurentb23d5282013-05-14 15:27:20 -07001881 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 if (out->pcm_device_id < 0) {
1883 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1884 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001885 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001886 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 }
1888
1889 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001890
1891 if (!uc_info) {
1892 ret = -ENOMEM;
1893 goto error_config;
1894 }
1895
Mingming Yin21854652016-04-13 11:54:02 -07001896 /* This must be called before adding this usecase to the list */
1897 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1898 /* This call can fail if compress pass thru is already active */
1899 check_and_set_hdmi_backend(out);
1900 }
1901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902 uc_info->id = out->usecase;
1903 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001904 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 uc_info->devices = out->devices;
1906 uc_info->in_snd_device = SND_DEVICE_NONE;
1907 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001908 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301910 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1911 adev->perf_lock_opts,
1912 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001913 select_devices(adev, out->usecase);
1914
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001915 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1916 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001917 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001918 unsigned int flags = PCM_OUT;
1919 unsigned int pcm_open_retry_count = 0;
1920 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1921 flags |= PCM_MMAP | PCM_NOIRQ;
1922 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1923 } else
1924 flags |= PCM_MONOTONIC;
1925
1926 while (1) {
1927 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1928 flags, &out->config);
1929 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1930 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1931 if (out->pcm != NULL) {
1932 pcm_close(out->pcm);
1933 out->pcm = NULL;
1934 }
1935 if (pcm_open_retry_count-- == 0) {
1936 ret = -EIO;
1937 goto error_open;
1938 }
1939 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1940 continue;
1941 }
1942 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001944
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001945 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1946 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001947
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001948 ALOGV("%s: pcm_prepare", __func__);
1949 if (pcm_is_ready(out->pcm)) {
1950 ret = pcm_prepare(out->pcm);
1951 if (ret < 0) {
1952 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1953 pcm_close(out->pcm);
1954 out->pcm = NULL;
1955 goto error_open;
1956 }
1957 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001958 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001959 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1960 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001962 out->compr = compress_open(adev->snd_card,
1963 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 COMPRESS_IN, &out->compr_config);
1965 if (out->compr && !is_compress_ready(out->compr)) {
1966 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1967 compress_close(out->compr);
1968 out->compr = NULL;
1969 ret = -EIO;
1970 goto error_open;
1971 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301972 /* compress_open sends params of the track, so reset the flag here */
1973 out->is_compr_metadata_avail = false;
1974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001975 if (out->offload_callback)
1976 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001977
Fred Oh3f43e742015-03-04 18:42:34 -08001978 /* Since small bufs uses blocking writes, a write will be blocked
1979 for the default max poll time (20s) in the event of an SSR.
1980 Reduce the poll time to observe and deal with SSR faster.
1981 */
Ashish Jain5106d362016-05-11 19:23:33 +05301982 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001983 compress_set_max_poll_wait(out->compr, 1000);
1984 }
1985
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001986 audio_extn_dts_create_state_notifier_node(out->usecase);
1987 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1988 popcount(out->channel_mask),
1989 out->playback_started);
1990
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001991#ifdef DS1_DOLBY_DDP_ENABLED
1992 if (audio_extn_is_dolby_format(out->format))
1993 audio_extn_dolby_send_ddp_endp_params(adev);
1994#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301995 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001996 if (adev->visualizer_start_output != NULL)
1997 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1998 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301999 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002000 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302003 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002004 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302008 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002010error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302011 /*
2012 * sleep 50ms to allow sufficient time for kernel
2013 * drivers to recover incases like SSR.
2014 */
2015 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002016 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017}
2018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019static int check_input_parameters(uint32_t sample_rate,
2020 audio_format_t format,
2021 int channel_count)
2022{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002023 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302025 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2026 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2027 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002028 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302029 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002030
2031 switch (channel_count) {
2032 case 1:
2033 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302034 case 3:
2035 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002036 case 6:
2037 break;
2038 default:
2039 ret = -EINVAL;
2040 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041
2042 switch (sample_rate) {
2043 case 8000:
2044 case 11025:
2045 case 12000:
2046 case 16000:
2047 case 22050:
2048 case 24000:
2049 case 32000:
2050 case 44100:
2051 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302052 case 96000:
2053 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 break;
2055 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002056 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 }
2058
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002059 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060}
2061
2062static size_t get_input_buffer_size(uint32_t sample_rate,
2063 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002064 int channel_count,
2065 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066{
2067 size_t size = 0;
2068
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002069 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2070 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002072 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002073 if (is_low_latency)
2074 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302075
2076 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002078 /* make sure the size is multiple of 32 bytes
2079 * At 48 kHz mono 16-bit PCM:
2080 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2081 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2082 */
2083 size += 0x1f;
2084 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002085
2086 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087}
2088
Ashish Jain5106d362016-05-11 19:23:33 +05302089static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2090{
2091 uint64_t actual_frames_rendered = 0;
2092 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2093
2094 /* This adjustment accounts for buffering after app processor.
2095 * It is based on estimated DSP latency per use case, rather than exact.
2096 */
2097 int64_t platform_latency = platform_render_latency(out->usecase) *
2098 out->sample_rate / 1000000LL;
2099
2100 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2101 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2102 * hence only estimate.
2103 */
2104 int64_t signed_frames = out->written - kernel_buffer_size;
2105
2106 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2107
2108 if (signed_frames > 0)
2109 actual_frames_rendered = signed_frames;
2110
2111 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2112 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2113 (long long int)out->written, (int)kernel_buffer_size,
2114 audio_bytes_per_sample(out->compr_config.codec->format),
2115 popcount(out->channel_mask));
2116
2117 return actual_frames_rendered;
2118}
2119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2121{
2122 struct stream_out *out = (struct stream_out *)stream;
2123
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125}
2126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002127static int out_set_sample_rate(struct audio_stream *stream __unused,
2128 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129{
2130 return -ENOSYS;
2131}
2132
2133static size_t out_get_buffer_size(const struct audio_stream *stream)
2134{
2135 struct stream_out *out = (struct stream_out *)stream;
2136
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002137 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002139 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2140 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302141 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
2142 return out->compr_pcm_config.hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002144 return out->config.period_size *
2145 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146}
2147
2148static uint32_t out_get_channels(const struct audio_stream *stream)
2149{
2150 struct stream_out *out = (struct stream_out *)stream;
2151
2152 return out->channel_mask;
2153}
2154
2155static audio_format_t out_get_format(const struct audio_stream *stream)
2156{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 struct stream_out *out = (struct stream_out *)stream;
2158
2159 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160}
2161
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002162static int out_set_format(struct audio_stream *stream __unused,
2163 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164{
2165 return -ENOSYS;
2166}
2167
2168static int out_standby(struct audio_stream *stream)
2169{
2170 struct stream_out *out = (struct stream_out *)stream;
2171 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302173 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2174 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002175 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2176 /* Ignore standby in case of voip call because the voip output
2177 * stream is closed in adev_close_output_stream()
2178 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302179 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002180 return 0;
2181 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002183 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002185 if (adev->adm_deregister_stream)
2186 adev->adm_deregister_stream(adev->adm_data, out->handle);
2187
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002188 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002190 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 if (out->pcm) {
2192 pcm_close(out->pcm);
2193 out->pcm = NULL;
2194 }
2195 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002196 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302198 out->send_next_track_params = false;
2199 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002200 out->gapless_mdata.encoder_delay = 0;
2201 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 if (out->compr != NULL) {
2203 compress_close(out->compr);
2204 out->compr = NULL;
2205 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002206 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002208 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 }
2210 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302211 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 return 0;
2213}
2214
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002215static int out_dump(const struct audio_stream *stream __unused,
2216 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217{
2218 return 0;
2219}
2220
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002221static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2222{
2223 int ret = 0;
2224 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002225
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002226 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002227 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228 return -EINVAL;
2229 }
2230
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302231 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002232
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002233 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2234 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302235 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002236 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002237 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2238 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302239 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002240 }
2241
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002242 ALOGV("%s new encoder delay %u and padding %u", __func__,
2243 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2244
2245 return 0;
2246}
2247
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002248static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2249{
2250 return out == adev->primary_output || out == adev->voice_tx_output;
2251}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2254{
2255 struct stream_out *out = (struct stream_out *)stream;
2256 struct audio_device *adev = out->dev;
2257 struct str_parms *parms;
2258 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002259 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260
sangwoobc677242013-08-08 16:53:43 +09002261 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002262 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302264 if (!parms)
2265 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002266 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2267 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002269 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002270 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002272 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002273 * When HDMI cable is unplugged the music playback is paused and
2274 * the policy manager sends routing=0. But the audioflinger continues
2275 * to write data until standby time (3sec). As the HDMI core is
2276 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 * Avoid this by routing audio to speaker until standby.
2278 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002279 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2280 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302281 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002282 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2283 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002284 }
2285
2286 /*
2287 * select_devices() call below switches all the usecases on the same
2288 * backend to the new device. Refer to check_usecases_codec_backend() in
2289 * the select_devices(). But how do we undo this?
2290 *
2291 * For example, music playback is active on headset (deep-buffer usecase)
2292 * and if we go to ringtones and select a ringtone, low-latency usecase
2293 * will be started on headset+speaker. As we can't enable headset+speaker
2294 * and headset devices at the same time, select_devices() switches the music
2295 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2296 * So when the ringtone playback is completed, how do we undo the same?
2297 *
2298 * We are relying on the out_set_parameters() call on deep-buffer output,
2299 * once the ringtone playback is ended.
2300 * NOTE: We should not check if the current devices are same as new devices.
2301 * Because select_devices() must be called to switch back the music
2302 * playback to headset.
2303 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002304 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002305 out->devices = val;
2306
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302307 if (!out->standby) {
2308 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2309 adev->perf_lock_opts,
2310 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002311 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302312 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2313 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002314
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002315 if (output_drives_call(adev, out)) {
2316 if(!voice_is_in_call(adev)) {
2317 if (adev->mode == AUDIO_MODE_IN_CALL) {
2318 adev->current_call_output = out;
2319 ret = voice_start_call(adev);
2320 }
2321 } else {
2322 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002323 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002324 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002325 }
2326 }
2327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002329 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002331
2332 if (out == adev->primary_output) {
2333 pthread_mutex_lock(&adev->lock);
2334 audio_extn_set_parameters(adev, parms);
2335 pthread_mutex_unlock(&adev->lock);
2336 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002337 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002338 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002339 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002340
2341 audio_extn_dts_create_state_notifier_node(out->usecase);
2342 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2343 popcount(out->channel_mask),
2344 out->playback_started);
2345
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002346 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002347 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302350error:
Eric Laurent994a6932013-07-17 11:51:42 -07002351 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 return ret;
2353}
2354
2355static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2356{
2357 struct stream_out *out = (struct stream_out *)stream;
2358 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002359 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 char value[256];
2361 struct str_parms *reply = str_parms_create();
2362 size_t i, j;
2363 int ret;
2364 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002365
2366 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002367 if (reply) {
2368 str_parms_destroy(reply);
2369 }
2370 if (query) {
2371 str_parms_destroy(query);
2372 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002373 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2374 return NULL;
2375 }
2376
Eric Laurent994a6932013-07-17 11:51:42 -07002377 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2379 if (ret >= 0) {
2380 value[0] = '\0';
2381 i = 0;
2382 while (out->supported_channel_masks[i] != 0) {
2383 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2384 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2385 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002386 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002388 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 first = false;
2390 break;
2391 }
2392 }
2393 i++;
2394 }
2395 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2396 str = str_parms_to_str(reply);
2397 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002398 voice_extn_out_get_parameters(out, query, reply);
2399 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002400 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002401 free(str);
2402 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002403 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002405
Alexy Joseph62142aa2015-11-16 15:10:34 -08002406
2407 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2408 if (ret >= 0) {
2409 value[0] = '\0';
2410 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2411 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302412 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002413 } else {
2414 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302415 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002416 }
2417 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002418 if (str)
2419 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002420 str = str_parms_to_str(reply);
2421 }
2422
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002423 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2424 if (ret >= 0) {
2425 value[0] = '\0';
2426 i = 0;
2427 first = true;
2428 while (out->supported_formats[i] != 0) {
2429 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2430 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2431 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002432 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002433 }
2434 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2435 first = false;
2436 break;
2437 }
2438 }
2439 i++;
2440 }
2441 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002442 if (str)
2443 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002444 str = str_parms_to_str(reply);
2445 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002446
2447 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2448 if (ret >= 0) {
2449 value[0] = '\0';
2450 i = 0;
2451 first = true;
2452 while (out->supported_sample_rates[i] != 0) {
2453 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2454 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2455 if (!first) {
2456 strlcat(value, "|", sizeof(value));
2457 }
2458 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2459 first = false;
2460 break;
2461 }
2462 }
2463 i++;
2464 }
2465 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2466 if (str)
2467 free(str);
2468 str = str_parms_to_str(reply);
2469 }
2470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 str_parms_destroy(query);
2472 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002473 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 return str;
2475}
2476
2477static uint32_t out_get_latency(const struct audio_stream_out *stream)
2478{
2479 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002480 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481
Alexy Josephaa54c872014-12-03 02:46:47 -08002482 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002483 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002484 } else {
2485 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002487 }
2488
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302489 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002490 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491}
2492
2493static int out_set_volume(struct audio_stream_out *stream, float left,
2494 float right)
2495{
Eric Laurenta9024de2013-04-04 09:19:12 -07002496 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 int volume[2];
2498
Eric Laurenta9024de2013-04-04 09:19:12 -07002499 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2500 /* only take left channel into account: the API is for stereo anyway */
2501 out->muted = (left == 0.0f);
2502 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002503 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302504 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002505 /*
2506 * Set mute or umute on HDMI passthrough stream.
2507 * Only take left channel into account.
2508 * Mute is 0 and unmute 1
2509 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302510 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002511 } else {
2512 char mixer_ctl_name[128];
2513 struct audio_device *adev = out->dev;
2514 struct mixer_ctl *ctl;
2515 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002516 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002518 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2519 "Compress Playback %d Volume", pcm_device_id);
2520 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2521 if (!ctl) {
2522 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2523 __func__, mixer_ctl_name);
2524 return -EINVAL;
2525 }
2526 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2527 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2528 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2529 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002531 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 return -ENOSYS;
2534}
2535
2536static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2537 size_t bytes)
2538{
2539 struct stream_out *out = (struct stream_out *)stream;
2540 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302541 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002542 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002544 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302545
Naresh Tanniru80659832014-06-04 18:17:56 +05302546 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002547
Ashish Jainbbce4322016-02-16 13:25:27 +05302548 if (is_offload_usecase(out->usecase)) {
2549 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302550 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2551 pthread_mutex_unlock(&out->lock);
2552 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302553 } else {
2554 /* increase written size during SSR to avoid mismatch
2555 * with the written frames count in AF
2556 */
2557 out->written += bytes / (out->config.channels * sizeof(short));
2558 ALOGD(" %s: sound card is not active/SSR state", __func__);
2559 ret= -EIO;
2560 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302561 }
2562 }
2563
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302564 if (audio_extn_passthru_should_drop_data(out)) {
2565 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2566 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2567 out_get_sample_rate(&out->stream.common));
2568 goto exit;
2569 }
2570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002572 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002573 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2575 ret = voice_extn_compress_voip_start_output_stream(out);
2576 else
2577 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002578 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002579 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002581 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 goto exit;
2583 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002584
2585 if (last_known_cal_step != -1) {
2586 ALOGD("%s: retry previous failed cal level set", __func__);
2587 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2588 }
2589
vivek mehta446c3962015-09-14 10:57:35 -07002590 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002591 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
Ashish Jain81eb2a82015-05-13 10:52:34 +05302594 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002595 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302596 adev->is_channel_status_set = true;
2597 }
2598
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002599 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002600 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002601 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002602 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002603 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2604 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302605 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2606 ALOGD("copl(%p):send next track params in gapless", out);
2607 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2608 out->send_next_track_params = false;
2609 out->is_compr_metadata_avail = false;
2610 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002611 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302612 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
2613 (out->compr_pcm_config.convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002614
Ashish Jainf1eaa582016-05-23 20:54:24 +05302615 if ((bytes > out->compr_pcm_config.hal_fragment_size)) {
2616 ALOGW("Error written bytes %zu > %d (fragment_size)",
2617 bytes, out->compr_pcm_config.hal_fragment_size);
2618 pthread_mutex_unlock(&out->lock);
2619 return -EINVAL;
2620 } else {
2621 audio_format_t dst_format = out->compr_pcm_config.hal_op_format;
2622 audio_format_t src_format = out->compr_pcm_config.hal_ip_format;
2623
2624 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2625 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2626
2627 memcpy_by_audio_format(out->compr_pcm_config.convert_buffer,
2628 dst_format,
2629 buffer,
2630 src_format,
2631 frames);
2632
2633 ret = compress_write(out->compr, out->compr_pcm_config.convert_buffer,
2634 bytes_to_write);
2635
2636 /*Convert written bytes in audio flinger format*/
2637 if (ret > 0)
2638 ret = ((ret * format_to_bitwidth_table[out->format]) /
2639 format_to_bitwidth_table[dst_format]);
2640 }
2641 } else
2642 ret = compress_write(out->compr, buffer, bytes);
2643
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302644 if (ret < 0)
2645 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302646 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002647 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302648 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002649 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302650 } else if (-ENETRESET == ret) {
2651 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2652 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2653 pthread_mutex_unlock(&out->lock);
2654 out_standby(&out->stream.common);
2655 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 }
Ashish Jain5106d362016-05-11 19:23:33 +05302657 if ( ret == (ssize_t)bytes && !out->non_blocking)
2658 out->written += bytes;
2659
Naresh Tanniru80659832014-06-04 18:17:56 +05302660 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002661 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002662 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 out->playback_started = 1;
2664 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002665
2666 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2667 popcount(out->channel_mask),
2668 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002669 }
2670 pthread_mutex_unlock(&out->lock);
2671 return ret;
2672 } else {
2673 if (out->pcm) {
2674 if (out->muted)
2675 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002676
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302677 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002678
2679 if (adev->adm_request_focus)
2680 adev->adm_request_focus(adev->adm_data, out->handle);
2681
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002682 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2683 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2684 else
2685 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002686
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302687 if (ret < 0)
2688 ret = -errno;
2689 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002690 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002691
2692 if (adev->adm_abandon_focus)
2693 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002694 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
2696
2697exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302698 /* ToDo: There may be a corner case when SSR happens back to back during
2699 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302700 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302701 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302702 }
2703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 pthread_mutex_unlock(&out->lock);
2705
2706 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002707 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002708 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302709 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302710 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302711 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302712 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302713 out->standby = true;
2714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302716 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302717 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 }
2719 return bytes;
2720}
2721
2722static int out_get_render_position(const struct audio_stream_out *stream,
2723 uint32_t *dsp_frames)
2724{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002725 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302726 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002727
2728 if (dsp_frames == NULL)
2729 return -EINVAL;
2730
2731 *dsp_frames = 0;
2732 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002733 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302734
2735 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2736 * this operation and adev_close_output_stream(where out gets reset).
2737 */
2738 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2739 *dsp_frames = get_actual_pcm_frames_rendered(out);
2740 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2741 return 0;
2742 }
2743
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002744 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302745 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302746 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002747 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302748 if (ret < 0)
2749 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302751 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 }
2753 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302754 if (-ENETRESET == ret) {
2755 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2756 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2757 return -EINVAL;
2758 } else if(ret < 0) {
2759 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2760 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302761 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2762 /*
2763 * Handle corner case where compress session is closed during SSR
2764 * and timestamp is queried
2765 */
2766 ALOGE(" ERROR: sound card not active, return error");
2767 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302768 } else {
2769 return 0;
2770 }
Zhou Song32a556e2015-05-05 10:46:56 +08002771 } else if (audio_is_linear_pcm(out->format)) {
2772 *dsp_frames = out->written;
2773 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002774 } else
2775 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776}
2777
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002778static int out_add_audio_effect(const struct audio_stream *stream __unused,
2779 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780{
2781 return 0;
2782}
2783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002784static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2785 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786{
2787 return 0;
2788}
2789
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002790static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2791 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792{
2793 return -EINVAL;
2794}
2795
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002796static int out_get_presentation_position(const struct audio_stream_out *stream,
2797 uint64_t *frames, struct timespec *timestamp)
2798{
2799 struct stream_out *out = (struct stream_out *)stream;
2800 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002801 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002802
Ashish Jain5106d362016-05-11 19:23:33 +05302803 /* below piece of code is not guarded against any lock because audioFliner serializes
2804 * this operation and adev_close_output_stream( where out gets reset).
2805 */
2806 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2807 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2808 *frames = get_actual_pcm_frames_rendered(out);
2809 /* this is the best we can do */
2810 clock_gettime(CLOCK_MONOTONIC, timestamp);
2811 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2812 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2813 return 0;
2814 }
2815
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002816 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002817
Ashish Jain5106d362016-05-11 19:23:33 +05302818 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2819 ret = compress_get_tstamp(out->compr, &dsp_frames,
2820 &out->sample_rate);
2821 ALOGVV("%s rendered frames %ld sample_rate %d",
2822 __func__, dsp_frames, out->sample_rate);
2823 *frames = dsp_frames;
2824 if (ret < 0)
2825 ret = -errno;
2826 if (-ENETRESET == ret) {
2827 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2828 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2829 ret = -EINVAL;
2830 } else
2831 ret = 0;
2832 /* this is the best we can do */
2833 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002834 } else {
2835 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002836 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002837 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2838 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002839 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002840 // This adjustment accounts for buffering after app processor.
2841 // It is based on estimated DSP latency per use case, rather than exact.
2842 signed_frames -=
2843 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2844
Eric Laurent949a0892013-09-20 09:20:13 -07002845 // It would be unusual for this value to be negative, but check just in case ...
2846 if (signed_frames >= 0) {
2847 *frames = signed_frames;
2848 ret = 0;
2849 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002850 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302851 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2852 *frames = out->written;
2853 clock_gettime(CLOCK_MONOTONIC, timestamp);
2854 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002855 }
2856 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002857 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002858 return ret;
2859}
2860
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861static int out_set_callback(struct audio_stream_out *stream,
2862 stream_callback_t callback, void *cookie)
2863{
2864 struct stream_out *out = (struct stream_out *)stream;
2865
2866 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002867 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 out->offload_callback = callback;
2869 out->offload_cookie = cookie;
2870 pthread_mutex_unlock(&out->lock);
2871 return 0;
2872}
2873
2874static int out_pause(struct audio_stream_out* stream)
2875{
2876 struct stream_out *out = (struct stream_out *)stream;
2877 int status = -ENOSYS;
2878 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002879 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002880 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002881 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302883 struct audio_device *adev = out->dev;
2884 int snd_scard_state = get_snd_card_state(adev);
2885
2886 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2887 status = compress_pause(out->compr);
2888
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002890
Mingming Yin21854652016-04-13 11:54:02 -07002891 if (audio_extn_passthru_is_active()) {
2892 ALOGV("offload use case, pause passthru");
2893 audio_extn_passthru_on_pause(out);
2894 }
2895
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302896 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002897 audio_extn_dts_notify_playback_state(out->usecase, 0,
2898 out->sample_rate, popcount(out->channel_mask),
2899 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 }
2901 pthread_mutex_unlock(&out->lock);
2902 }
2903 return status;
2904}
2905
2906static int out_resume(struct audio_stream_out* stream)
2907{
2908 struct stream_out *out = (struct stream_out *)stream;
2909 int status = -ENOSYS;
2910 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002911 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002912 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002914 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302916 struct audio_device *adev = out->dev;
2917 int snd_scard_state = get_snd_card_state(adev);
2918
Mingming Yin21854652016-04-13 11:54:02 -07002919 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2920 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2921 pthread_mutex_lock(&out->dev->lock);
2922 ALOGV("offload resume, check and set hdmi backend again");
2923 check_and_set_hdmi_backend(out);
2924 pthread_mutex_unlock(&out->dev->lock);
2925 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302926 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002927 }
2928 if (!status) {
2929 out->offload_state = OFFLOAD_STATE_PLAYING;
2930 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302931 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002932 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2933 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 }
2935 pthread_mutex_unlock(&out->lock);
2936 }
2937 return status;
2938}
2939
2940static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2941{
2942 struct stream_out *out = (struct stream_out *)stream;
2943 int status = -ENOSYS;
2944 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002945 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002946 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2948 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2949 else
2950 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2951 pthread_mutex_unlock(&out->lock);
2952 }
2953 return status;
2954}
2955
2956static int out_flush(struct audio_stream_out* stream)
2957{
2958 struct stream_out *out = (struct stream_out *)stream;
2959 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002960 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002961 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002962 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302964 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002965 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002966 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 return 0;
2968 }
2969 return -ENOSYS;
2970}
2971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972/** audio_stream_in implementation **/
2973static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2974{
2975 struct stream_in *in = (struct stream_in *)stream;
2976
2977 return in->config.rate;
2978}
2979
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002980static int in_set_sample_rate(struct audio_stream *stream __unused,
2981 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982{
2983 return -ENOSYS;
2984}
2985
2986static size_t in_get_buffer_size(const struct audio_stream *stream)
2987{
2988 struct stream_in *in = (struct stream_in *)stream;
2989
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002990 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2991 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002992 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2993 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002994
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002995 return in->config.period_size *
2996 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997}
2998
2999static uint32_t in_get_channels(const struct audio_stream *stream)
3000{
3001 struct stream_in *in = (struct stream_in *)stream;
3002
3003 return in->channel_mask;
3004}
3005
3006static audio_format_t in_get_format(const struct audio_stream *stream)
3007{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003008 struct stream_in *in = (struct stream_in *)stream;
3009
3010 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011}
3012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003013static int in_set_format(struct audio_stream *stream __unused,
3014 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015{
3016 return -ENOSYS;
3017}
3018
3019static int in_standby(struct audio_stream *stream)
3020{
3021 struct stream_in *in = (struct stream_in *)stream;
3022 struct audio_device *adev = in->dev;
3023 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303024 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3025 stream, in->usecase, use_case_table[in->usecase]);
3026
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003027 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3028 /* Ignore standby in case of voip call because the voip input
3029 * stream is closed in adev_close_input_stream()
3030 */
3031 ALOGV("%s: Ignore Standby in VOIP call", __func__);
3032 return status;
3033 }
3034
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003035 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003036 if (!in->standby && in->is_st_session) {
3037 ALOGD("%s: sound trigger pcm stop lab", __func__);
3038 audio_extn_sound_trigger_stop_lab(in);
3039 in->standby = 1;
3040 }
3041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003043 if (adev->adm_deregister_stream)
3044 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3045
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003046 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003048 if (in->pcm) {
3049 pcm_close(in->pcm);
3050 in->pcm = NULL;
3051 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003053 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 }
3055 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003056 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 return status;
3058}
3059
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003060static int in_dump(const struct audio_stream *stream __unused,
3061 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062{
3063 return 0;
3064}
3065
3066static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3067{
3068 struct stream_in *in = (struct stream_in *)stream;
3069 struct audio_device *adev = in->dev;
3070 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003072 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303074 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 parms = str_parms_create_str(kvpairs);
3076
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303077 if (!parms)
3078 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003079 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003080 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003081
3082 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3083 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 val = atoi(value);
3085 /* no audio source uses val == 0 */
3086 if ((in->source != val) && (val != 0)) {
3087 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003088 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3089 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3090 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003091 (in->config.rate == 8000 || in->config.rate == 16000 ||
3092 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003093 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003094 err = voice_extn_compress_voip_open_input_stream(in);
3095 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003096 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003097 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003098 }
3099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 }
3101 }
3102
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003103 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3104 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003106 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 in->device = val;
3108 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003109 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003110 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 }
3112 }
3113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003115 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
3117 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303118error:
Eric Laurent994a6932013-07-17 11:51:42 -07003119 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 return ret;
3121}
3122
3123static char* in_get_parameters(const struct audio_stream *stream,
3124 const char *keys)
3125{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003126 struct stream_in *in = (struct stream_in *)stream;
3127 struct str_parms *query = str_parms_create_str(keys);
3128 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003129 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003130
3131 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003132 if (reply) {
3133 str_parms_destroy(reply);
3134 }
3135 if (query) {
3136 str_parms_destroy(query);
3137 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003138 ALOGE("in_get_parameters: failed to create query or reply");
3139 return NULL;
3140 }
3141
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003142 ALOGV("%s: enter: keys - %s", __func__, keys);
3143
3144 voice_extn_in_get_parameters(in, query, reply);
3145
3146 str = str_parms_to_str(reply);
3147 str_parms_destroy(query);
3148 str_parms_destroy(reply);
3149
3150 ALOGV("%s: exit: returns - %s", __func__, str);
3151 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152}
3153
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003154static int in_set_gain(struct audio_stream_in *stream __unused,
3155 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156{
3157 return 0;
3158}
3159
3160static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3161 size_t bytes)
3162{
3163 struct stream_in *in = (struct stream_in *)stream;
3164 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303165 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303166 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303167 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003169 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003171 if (in->is_st_session) {
3172 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3173 /* Read from sound trigger HAL */
3174 audio_extn_sound_trigger_read(in, buffer, bytes);
3175 pthread_mutex_unlock(&in->lock);
3176 return bytes;
3177 }
3178
Ashish Jainbbce4322016-02-16 13:25:27 +05303179 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003180 ALOGD(" %s: sound card is not active/SSR state", __func__);
3181 ret= -EIO;;
3182 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303183 }
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003186 pthread_mutex_lock(&adev->lock);
3187 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3188 ret = voice_extn_compress_voip_start_input_stream(in);
3189 else
3190 ret = start_input_stream(in);
3191 pthread_mutex_unlock(&adev->lock);
3192 if (ret != 0) {
3193 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 }
3195 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003196 if (adev->adm_register_input_stream)
3197 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003200 if (adev->adm_request_focus)
3201 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303204 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003205 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303206 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003207 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303208 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003209 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303210 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003211 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303212 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3213 if (bytes % 4 == 0) {
3214 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3215 int_buf_stream = buffer;
3216 for (size_t itt=0; itt < bytes/4 ; itt++) {
3217 int_buf_stream[itt] >>= 8;
3218 }
3219 } else {
3220 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3221 ret = -EINVAL;
3222 goto exit;
3223 }
3224 } if (ret < 0) {
3225 ret = -errno;
3226 }
3227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 }
3229
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003230 if (adev->adm_abandon_focus)
3231 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 /*
3234 * Instead of writing zeroes here, we could trust the hardware
3235 * to always provide zeroes when muted.
3236 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303237 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3238 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 memset(buffer, 0, bytes);
3240
3241exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303242 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303243 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003244 if (-ENETRESET == ret)
3245 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 pthread_mutex_unlock(&in->lock);
3248
3249 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303250 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303251 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303252 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303253 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303254 in->standby = true;
3255 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303256 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003258 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303259 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303260 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 }
3262 return bytes;
3263}
3264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003265static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266{
3267 return 0;
3268}
3269
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003270static int add_remove_audio_effect(const struct audio_stream *stream,
3271 effect_handle_t effect,
3272 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003274 struct stream_in *in = (struct stream_in *)stream;
3275 int status = 0;
3276 effect_descriptor_t desc;
3277
3278 status = (*effect)->get_descriptor(effect, &desc);
3279 if (status != 0)
3280 return status;
3281
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003282 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003283 pthread_mutex_lock(&in->dev->lock);
3284 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3285 in->enable_aec != enable &&
3286 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3287 in->enable_aec = enable;
3288 if (!in->standby)
3289 select_devices(in->dev, in->usecase);
3290 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003291 if (in->enable_ns != enable &&
3292 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3293 in->enable_ns = enable;
3294 if (!in->standby)
3295 select_devices(in->dev, in->usecase);
3296 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003297 pthread_mutex_unlock(&in->dev->lock);
3298 pthread_mutex_unlock(&in->lock);
3299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 return 0;
3301}
3302
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003303static int in_add_audio_effect(const struct audio_stream *stream,
3304 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305{
Eric Laurent994a6932013-07-17 11:51:42 -07003306 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003307 return add_remove_audio_effect(stream, effect, true);
3308}
3309
3310static int in_remove_audio_effect(const struct audio_stream *stream,
3311 effect_handle_t effect)
3312{
Eric Laurent994a6932013-07-17 11:51:42 -07003313 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003314 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315}
3316
3317static int adev_open_output_stream(struct audio_hw_device *dev,
3318 audio_io_handle_t handle,
3319 audio_devices_t devices,
3320 audio_output_flags_t flags,
3321 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003322 struct audio_stream_out **stream_out,
3323 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324{
3325 struct audio_device *adev = (struct audio_device *)dev;
3326 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303327 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003328 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303331
3332 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3333 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003334 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303335 return -EINVAL;
3336 }
3337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3339
Mingming Yin3a941d42016-02-17 18:08:05 -08003340 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3341 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303342 devices, flags, &out->stream);
3343
3344
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003345 if (!out) {
3346 return -ENOMEM;
3347 }
3348
Haynes Mathew George204045b2015-02-25 20:32:03 -08003349 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003350 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003351 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 if (devices == AUDIO_DEVICE_NONE)
3354 devices = AUDIO_DEVICE_OUT_SPEAKER;
3355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 out->flags = flags;
3357 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003358 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003359 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360 out->sample_rate = config->sample_rate;
3361 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3362 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003363 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003364 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003365 out->non_blocking = 0;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303366 out->compr_pcm_config.convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367
Mingming Yin3a941d42016-02-17 18:08:05 -08003368 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3369 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3370 pthread_mutex_lock(&adev->lock);
3371 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3372 ret = read_hdmi_sink_caps(out);
3373 pthread_mutex_unlock(&adev->lock);
3374 if (ret != 0) {
3375 if (ret == -ENOSYS) {
3376 /* ignore and go with default */
3377 ret = 0;
3378 } else {
3379 ALOGE("error reading hdmi sink caps");
3380 goto error_open;
3381 }
3382 }
3383 }
3384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003386 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303387 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3388 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003389 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3390 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3391
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003392 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003393 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3394 /*
3395 * Do not handle stereo output in Multi-channel cases
3396 * Stereo case is handled in normal playback path
3397 */
3398 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3399 ret = AUDIO_CHANNEL_OUT_STEREO;
3400 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003401
3402 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3403 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003404 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003405 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003406 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003407
3408 if (config->sample_rate == 0)
3409 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3410 if (config->channel_mask == 0)
3411 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003412 if (config->format == 0)
3413 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003414
3415 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003417 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3419 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003421 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003423 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3424 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003425 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003426 ret = voice_extn_compress_voip_open_output_stream(out);
3427 if (ret != 0) {
3428 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3429 __func__, ret);
3430 goto error_open;
3431 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003432 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3433 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3434
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3436 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3437 ALOGE("%s: Unsupported Offload information", __func__);
3438 ret = -EINVAL;
3439 goto error_open;
3440 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003441
Mingming Yin3a941d42016-02-17 18:08:05 -08003442 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003443 if(config->offload_info.format == 0)
3444 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003445 if (config->offload_info.sample_rate == 0)
3446 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003447 }
3448
Mingming Yin90310102013-11-13 16:57:00 -08003449 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303450 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003451 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003452 ret = -EINVAL;
3453 goto error_open;
3454 }
3455
3456 out->compr_config.codec = (struct snd_codec *)
3457 calloc(1, sizeof(struct snd_codec));
3458
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003459 if (!out->compr_config.codec) {
3460 ret = -ENOMEM;
3461 goto error_open;
3462 }
3463
vivek mehta0ea887a2015-08-26 14:01:20 -07003464 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303465 out->stream.pause = out_pause;
3466 out->stream.flush = out_flush;
3467 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003468 out->usecase = get_offload_usecase(adev, true);
3469 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003470 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003471 out->stream.set_callback = out_set_callback;
3472 out->stream.pause = out_pause;
3473 out->stream.resume = out_resume;
3474 out->stream.drain = out_drain;
3475 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003476 out->usecase = get_offload_usecase(adev, false);
3477 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003478 }
vivek mehta446c3962015-09-14 10:57:35 -07003479
3480 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003481 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3482 config->format == 0 && config->sample_rate == 0 &&
3483 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003484 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003485 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3486 } else {
3487 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3488 ret = -EEXIST;
3489 goto error_open;
3490 }
vivek mehta446c3962015-09-14 10:57:35 -07003491 }
3492
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003493 if (config->offload_info.channel_mask)
3494 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003495 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003497 config->offload_info.channel_mask = config->channel_mask;
3498 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003499 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 out->sample_rate = config->offload_info.sample_rate;
3501
Mingming Yin3ee55c62014-08-04 14:23:35 -07003502 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003503
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303504 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3505 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3506 audio_extn_dolby_send_ddp_endp_params(adev);
3507 audio_extn_dolby_set_dmid(adev);
3508 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003509
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003511 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 out->compr_config.codec->bit_rate =
3513 config->offload_info.bit_rate;
3514 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003515 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003516 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303517 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003518 /*TODO: Do we need to change it for passthrough */
3519 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003520
Manish Dewangana6fc5442015-08-24 20:30:31 +05303521 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3522 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3523 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3524 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303525
3526 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3527 AUDIO_FORMAT_PCM) {
3528
3529 /*Based on platform support, configure appropriate alsa format for corresponding
3530 *hal input format.
3531 */
3532 out->compr_config.codec->format = hal_format_to_alsa(
3533 config->offload_info.format);
3534
3535 out->compr_pcm_config.hal_op_format = alsa_format_to_hal(
3536 out->compr_config.codec->format);
3537 out->compr_pcm_config.hal_ip_format = out->format;
3538
3539 /*for direct PCM playback populate bit_width based on selected alsa format as
3540 *hal input format and alsa format might differ based on platform support.
3541 */
3542 out->bit_width = audio_bytes_per_sample(
3543 out->compr_pcm_config.hal_op_format) << 3;
3544
3545 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3546
3547 /* Check if alsa session is configured with the same format as HAL input format,
3548 * if not then derive correct fragment size needed to accomodate the
3549 * conversion of HAL input format to alsa format.
3550 */
3551 audio_extn_utils_update_direct_pcm_fragment_size(out);
3552
3553 /*if hal input and output fragment size is different this indicates HAL input format is
3554 *not same as the alsa format
3555 */
3556 if (out->compr_pcm_config.hal_fragment_size != out->compr_config.fragment_size) {
3557 /*Allocate a buffer to convert input data to the alsa configured format.
3558 *size of convert buffer is equal to the size required to hold one fragment size
3559 *worth of pcm data, this is because flinger does not write more than fragment_size
3560 */
3561 out->compr_pcm_config.convert_buffer = calloc(1,out->compr_config.fragment_size);
3562 if (out->compr_pcm_config.convert_buffer == NULL){
3563 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3564 ret = -ENOMEM;
3565 goto error_open;
3566 }
3567 }
3568 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3569 out->compr_config.fragment_size =
3570 audio_extn_passthru_get_buffer_size(&config->offload_info);
3571 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3572 } else {
3573 out->compr_config.fragment_size =
3574 platform_get_compress_offload_buffer_size(&config->offload_info);
3575 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3576 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003577
Amit Shekhar6f461b12014-08-01 14:52:58 -07003578 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303579 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003580
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003581 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3582 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003583
Alexy Josephaa54c872014-12-03 02:46:47 -08003584
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003585 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303586 out->send_next_track_params = false;
3587 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003588 out->offload_state = OFFLOAD_STATE_IDLE;
3589 out->playback_started = 0;
3590
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003591 audio_extn_dts_create_state_notifier_node(out->usecase);
3592
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 create_offload_callback_thread(out);
3594 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3595 __func__, config->offload_info.version,
3596 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303597
3598 /* Disable gapless if any of the following is true
3599 * passthrough playback
3600 * AV playback
3601 * Direct PCM playback
3602 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303603 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303604 config->offload_info.has_video ||
3605 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3606 check_and_set_gapless_mode(adev, false);
3607 } else
3608 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003609
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303610 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003611 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3612 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003613 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303614 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003615 if (ret != 0) {
3616 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3617 __func__, ret);
3618 goto error_open;
3619 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003620 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3621 if (config->sample_rate == 0)
3622 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3623 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3624 config->sample_rate != 8000) {
3625 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3626 ret = -EINVAL;
3627 goto error_open;
3628 }
3629 out->sample_rate = config->sample_rate;
3630 out->config.rate = config->sample_rate;
3631 if (config->format == AUDIO_FORMAT_DEFAULT)
3632 config->format = AUDIO_FORMAT_PCM_16_BIT;
3633 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3634 config->format = AUDIO_FORMAT_PCM_16_BIT;
3635 ret = -EINVAL;
3636 goto error_open;
3637 }
3638 out->format = config->format;
3639 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3640 out->config = pcm_config_afe_proxy_playback;
3641 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003642 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3643 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3644 out->config = pcm_config_low_latency;
3645 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003646 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003647 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3649 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003650 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003651 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3652 format = AUDIO_FORMAT_PCM_16_BIT;
3653 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3654 out->config = pcm_config_deep_buffer;
3655 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003656 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003657 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003658 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003659 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003660 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003661 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 }
3663
Mingming Yin21854652016-04-13 11:54:02 -07003664 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3665 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003666 /* TODO remove this hardcoding and check why width is zero*/
3667 if (out->bit_width == 0)
3668 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003669 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3670 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003671 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303672 out->bit_width, out->channel_mask,
3673 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003674 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3675 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3676 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003677 if(adev->primary_output == NULL)
3678 adev->primary_output = out;
3679 else {
3680 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003681 ret = -EEXIST;
3682 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003683 }
3684 }
3685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 /* Check if this usecase is already existing */
3687 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003688 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3689 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003692 ret = -EEXIST;
3693 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694 }
3695 pthread_mutex_unlock(&adev->lock);
3696
3697 out->stream.common.get_sample_rate = out_get_sample_rate;
3698 out->stream.common.set_sample_rate = out_set_sample_rate;
3699 out->stream.common.get_buffer_size = out_get_buffer_size;
3700 out->stream.common.get_channels = out_get_channels;
3701 out->stream.common.get_format = out_get_format;
3702 out->stream.common.set_format = out_set_format;
3703 out->stream.common.standby = out_standby;
3704 out->stream.common.dump = out_dump;
3705 out->stream.common.set_parameters = out_set_parameters;
3706 out->stream.common.get_parameters = out_get_parameters;
3707 out->stream.common.add_audio_effect = out_add_audio_effect;
3708 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3709 out->stream.get_latency = out_get_latency;
3710 out->stream.set_volume = out_set_volume;
3711 out->stream.write = out_write;
3712 out->stream.get_render_position = out_get_render_position;
3713 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003714 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003717 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003718 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719
3720 config->format = out->stream.common.get_format(&out->stream.common);
3721 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3722 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3723
3724 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303725 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003726 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003727
3728 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3729 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3730 popcount(out->channel_mask), out->playback_started);
3731
Eric Laurent994a6932013-07-17 11:51:42 -07003732 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003734
3735error_open:
Ashish Jainf1eaa582016-05-23 20:54:24 +05303736 if (out->compr_pcm_config.convert_buffer)
3737 free(out->compr_pcm_config.convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003738 free(out);
3739 *stream_out = NULL;
3740 ALOGD("%s: exit: ret %d", __func__, ret);
3741 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742}
3743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003744static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 struct audio_stream_out *stream)
3746{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003747 struct stream_out *out = (struct stream_out *)stream;
3748 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003749 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003750
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303751 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3752
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003753 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303754 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003755 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303756 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003757 if(ret != 0)
3758 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3759 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003760 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003761 out_standby(&stream->common);
3762
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003763 if (is_offload_usecase(out->usecase)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303764 if (out->compr_pcm_config.convert_buffer != NULL)
3765 free(out->compr_pcm_config.convert_buffer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003766 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003767 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003768 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769 if (out->compr_config.codec != NULL)
3770 free(out->compr_config.codec);
3771 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003772
3773 if (adev->voice_tx_output == out)
3774 adev->voice_tx_output = NULL;
3775
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003776 pthread_cond_destroy(&out->cond);
3777 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003779 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780}
3781
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003782static void close_compress_sessions(struct audio_device *adev)
3783{
Mingming Yin7b762e72015-03-04 13:47:32 -08003784 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303785 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003786 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003787 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303788
3789 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003790 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303791 if (is_offload_usecase(usecase->id)) {
3792 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003793 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3794 out = usecase->stream.out;
3795 pthread_mutex_unlock(&adev->lock);
3796 out_standby(&out->stream.common);
3797 pthread_mutex_lock(&adev->lock);
3798 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303799 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003800 }
3801 pthread_mutex_unlock(&adev->lock);
3802}
3803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3805{
3806 struct audio_device *adev = (struct audio_device *)dev;
3807 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003809 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003810 int ret;
3811 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003813 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303816 if (!parms)
3817 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003818 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3819 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303820 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303821 if (strstr(snd_card_status, "OFFLINE")) {
3822 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303823 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003824 //close compress sessions on OFFLINE status
3825 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303826 } else if (strstr(snd_card_status, "ONLINE")) {
3827 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303828 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003829 //send dts hpx license if enabled
3830 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303831 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303832 }
3833
3834 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003835 status = voice_set_parameters(adev, parms);
3836 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003837 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003839 status = platform_set_parameters(adev->platform, parms);
3840 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003841 goto done;
3842
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003843 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3844 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003845 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3847 adev->bluetooth_nrec = true;
3848 else
3849 adev->bluetooth_nrec = false;
3850 }
3851
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003852 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3853 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3855 adev->screen_off = false;
3856 else
3857 adev->screen_off = true;
3858 }
3859
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003860 ret = str_parms_get_int(parms, "rotation", &val);
3861 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003862 bool reverse_speakers = false;
3863 switch(val) {
3864 // FIXME: note that the code below assumes that the speakers are in the correct placement
3865 // relative to the user when the device is rotated 90deg from its default rotation. This
3866 // assumption is device-specific, not platform-specific like this code.
3867 case 270:
3868 reverse_speakers = true;
3869 break;
3870 case 0:
3871 case 90:
3872 case 180:
3873 break;
3874 default:
3875 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003876 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003877 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003878 if (status == 0) {
3879 if (adev->speaker_lr_swap != reverse_speakers) {
3880 adev->speaker_lr_swap = reverse_speakers;
3881 // only update the selected device if there is active pcm playback
3882 struct audio_usecase *usecase;
3883 struct listnode *node;
3884 list_for_each(node, &adev->usecase_list) {
3885 usecase = node_to_item(node, struct audio_usecase, list);
3886 if (usecase->type == PCM_PLAYBACK) {
3887 select_devices(adev, usecase->id);
3888 break;
3889 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003890 }
3891 }
3892 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003893 }
3894
Mingming Yin514a8bc2014-07-29 15:22:21 -07003895 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3896 if (ret >= 0) {
3897 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3898 adev->bt_wb_speech_enabled = true;
3899 else
3900 adev->bt_wb_speech_enabled = false;
3901 }
3902
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003903 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3904 if (ret >= 0) {
3905 val = atoi(value);
3906 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3907 ALOGV("cache new edid");
3908 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003909 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3910 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07003911 /*
3912 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3913 * Per AudioPolicyManager, USB device is higher priority than WFD.
3914 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3915 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3916 * starting voice call on USB
3917 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003918 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3919 if (ret >= 0) {
3920 audio_extn_usb_add_device(val, atoi(value));
3921 }
vivek mehta344576a2016-04-12 18:56:03 -07003922 ALOGV("detected USB connect .. disable proxy");
3923 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003924 }
3925 }
3926
3927 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3928 if (ret >= 0) {
3929 val = atoi(value);
3930 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3931 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08003932 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003933 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3934 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
3935 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3936 if (ret >= 0) {
3937 audio_extn_usb_remove_device(val, atoi(value));
3938 }
vivek mehta344576a2016-04-12 18:56:03 -07003939 ALOGV("detected USB disconnect .. enable proxy");
3940 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003941 }
3942 }
3943
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003944 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003945
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003946done:
3947 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003948 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303949error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003950 ALOGV("%s: exit with code(%d)", __func__, status);
3951 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952}
3953
3954static char* adev_get_parameters(const struct audio_hw_device *dev,
3955 const char *keys)
3956{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003957 struct audio_device *adev = (struct audio_device *)dev;
3958 struct str_parms *reply = str_parms_create();
3959 struct str_parms *query = str_parms_create_str(keys);
3960 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303961 char value[256] = {0};
3962 int ret = 0;
3963
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003964 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003965 if (reply) {
3966 str_parms_destroy(reply);
3967 }
3968 if (query) {
3969 str_parms_destroy(query);
3970 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003971 ALOGE("adev_get_parameters: failed to create query or reply");
3972 return NULL;
3973 }
3974
Naresh Tannirud7205b62014-06-20 02:54:48 +05303975 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3976 sizeof(value));
3977 if (ret >=0) {
3978 int val = 1;
3979 pthread_mutex_lock(&adev->snd_card_status.lock);
3980 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3981 val = 0;
3982 pthread_mutex_unlock(&adev->snd_card_status.lock);
3983 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3984 goto exit;
3985 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003986
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003987 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003988 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003989 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003990 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303991 pthread_mutex_unlock(&adev->lock);
3992
Naresh Tannirud7205b62014-06-20 02:54:48 +05303993exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003994 str = str_parms_to_str(reply);
3995 str_parms_destroy(query);
3996 str_parms_destroy(reply);
3997
3998 ALOGV("%s: exit: returns - %s", __func__, str);
3999 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000}
4001
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004002static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003{
4004 return 0;
4005}
4006
4007static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4008{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004009 int ret;
4010 struct audio_device *adev = (struct audio_device *)dev;
4011 pthread_mutex_lock(&adev->lock);
4012 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004013 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004014 pthread_mutex_unlock(&adev->lock);
4015 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016}
4017
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004018static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4019 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020{
4021 return -ENOSYS;
4022}
4023
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004024static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4025 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026{
4027 return -ENOSYS;
4028}
4029
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004030static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4031 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032{
4033 return -ENOSYS;
4034}
4035
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004036static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4037 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038{
4039 return -ENOSYS;
4040}
4041
4042static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4043{
4044 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 pthread_mutex_lock(&adev->lock);
4047 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004048 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004050 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004051 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004052 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004053 adev->current_call_output = NULL;
4054 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 }
4056 pthread_mutex_unlock(&adev->lock);
4057 return 0;
4058}
4059
4060static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4061{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004062 int ret;
4063
4064 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004065 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004066 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4067 pthread_mutex_unlock(&adev->lock);
4068
4069 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070}
4071
4072static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4073{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004074 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 return 0;
4076}
4077
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004078static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079 const struct audio_config *config)
4080{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004081 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004083 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4084 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085}
4086
4087static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004088 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 audio_devices_t devices,
4090 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004091 struct audio_stream_in **stream_in,
4092 audio_input_flags_t flags __unused,
4093 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004094 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095{
4096 struct audio_device *adev = (struct audio_device *)dev;
4097 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004098 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004099 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004100 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304103 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4104 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304106 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107
4108 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004109
4110 if (!in) {
4111 ALOGE("failed to allocate input stream");
4112 return -ENOMEM;
4113 }
4114
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304115 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304116 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4117 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004118 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004119 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 in->stream.common.get_sample_rate = in_get_sample_rate;
4122 in->stream.common.set_sample_rate = in_set_sample_rate;
4123 in->stream.common.get_buffer_size = in_get_buffer_size;
4124 in->stream.common.get_channels = in_get_channels;
4125 in->stream.common.get_format = in_get_format;
4126 in->stream.common.set_format = in_set_format;
4127 in->stream.common.standby = in_standby;
4128 in->stream.common.dump = in_dump;
4129 in->stream.common.set_parameters = in_set_parameters;
4130 in->stream.common.get_parameters = in_get_parameters;
4131 in->stream.common.add_audio_effect = in_add_audio_effect;
4132 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4133 in->stream.set_gain = in_set_gain;
4134 in->stream.read = in_read;
4135 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4136
4137 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004138 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 in->standby = 1;
4141 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004142 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004143 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144
4145 /* Update config params with the requested sample rate and channels */
4146 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004147 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4148 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4149 is_low_latency = true;
4150#if LOW_LATENCY_CAPTURE_USE_CASE
4151 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4152#endif
4153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004156 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304157 in->bit_width = 16;
4158 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004160 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304161 if (adev->mode != AUDIO_MODE_IN_CALL) {
4162 ret = -EINVAL;
4163 goto err_open;
4164 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004165 if (config->sample_rate == 0)
4166 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4167 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4168 config->sample_rate != 8000) {
4169 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4170 ret = -EINVAL;
4171 goto err_open;
4172 }
4173 if (config->format == AUDIO_FORMAT_DEFAULT)
4174 config->format = AUDIO_FORMAT_PCM_16_BIT;
4175 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4176 config->format = AUDIO_FORMAT_PCM_16_BIT;
4177 ret = -EINVAL;
4178 goto err_open;
4179 }
4180
4181 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4182 in->config = pcm_config_afe_proxy_record;
4183 in->config.channels = channel_count;
4184 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304185 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304186 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4187 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004188 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004189 audio_extn_compr_cap_format_supported(config->format) &&
4190 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004191 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004192 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304193 /* restrict 24 bit capture for unprocessed source only
4194 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4195 */
4196 if (config->format == AUDIO_FORMAT_DEFAULT) {
4197 config->format = AUDIO_FORMAT_PCM_16_BIT;
4198 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4199 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4200 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4201 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4202 bool ret_error = false;
4203 in->bit_width = 24;
4204 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4205 from HAL is 24_packed and 8_24
4206 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4207 24_packed return error indicating supported format is 24_packed
4208 *> In case of any other source requesting 24 bit or float return error
4209 indicating format supported is 16 bit only.
4210
4211 on error flinger will retry with supported format passed
4212 */
4213 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4214 (source != AUDIO_SOURCE_CAMCORDER)) {
4215 config->format = AUDIO_FORMAT_PCM_16_BIT;
4216 if( config->sample_rate > 48000)
4217 config->sample_rate = 48000;
4218 ret_error = true;
4219 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4220 in->config.format = PCM_FORMAT_S24_3LE;
4221 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4222 in->config.format = PCM_FORMAT_S24_LE;
4223 } else {
4224 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4225 ret_error = true;
4226 }
4227
4228 if (ret_error) {
4229 ret = -EINVAL;
4230 goto err_open;
4231 }
4232 }
4233
4234 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004235 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004236 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004237 buffer_size = get_input_buffer_size(config->sample_rate,
4238 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004239 channel_count,
4240 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004241 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004242 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4243 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4244 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004245 (in->config.rate == 8000 || in->config.rate == 16000 ||
4246 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004247 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4248 voice_extn_compress_voip_open_input_stream(in);
4249 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004252 /* This stream could be for sound trigger lab,
4253 get sound trigger pcm if present */
4254 audio_extn_sound_trigger_check_and_get_session(in);
4255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004257 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004258 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259
4260err_open:
4261 free(in);
4262 *stream_in = NULL;
4263 return ret;
4264}
4265
4266static void adev_close_input_stream(struct audio_hw_device *dev,
4267 struct audio_stream_in *stream)
4268{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004269 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004270 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004271 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304272
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304273 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004274
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304275 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004276 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304277
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004278 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304279 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004280 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304281 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004282 if (ret != 0)
4283 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4284 __func__, ret);
4285 } else
4286 in_standby(&stream->common);
4287
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004288 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004289 audio_extn_ssr_deinit();
4290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291
Mingming Yine62d7842013-10-25 16:26:03 -07004292 if(audio_extn_compr_cap_enabled() &&
4293 audio_extn_compr_cap_format_supported(in->config.format))
4294 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004295
Mingming Yinfd7607b2016-01-22 12:48:44 -08004296 if (in->is_st_session) {
4297 ALOGV("%s: sound trigger pcm stop lab", __func__);
4298 audio_extn_sound_trigger_stop_lab(in);
4299 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004300 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301 return;
4302}
4303
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004304static int adev_dump(const audio_hw_device_t *device __unused,
4305 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306{
4307 return 0;
4308}
4309
4310static int adev_close(hw_device_t *device)
4311{
4312 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004313
4314 if (!adev)
4315 return 0;
4316
4317 pthread_mutex_lock(&adev_init_lock);
4318
4319 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004320 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004321 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004322 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004323 audio_route_free(adev->audio_route);
4324 free(adev->snd_dev_ref_cnt);
4325 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004326 if (adev->adm_deinit)
4327 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004328 free(device);
4329 adev = NULL;
4330 }
4331 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 return 0;
4334}
4335
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004336/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4337 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4338 * just that it _might_ work.
4339 */
4340static int period_size_is_plausible_for_low_latency(int period_size)
4341{
4342 switch (period_size) {
4343 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004344 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004345 case 240:
4346 case 320:
4347 case 480:
4348 return 1;
4349 default:
4350 return 0;
4351 }
4352}
4353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354static int adev_open(const hw_module_t *module, const char *name,
4355 hw_device_t **device)
4356{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004357 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4359
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004360 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004361 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004362 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004363 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004364 ALOGD("%s: returning existing instance of adev", __func__);
4365 ALOGD("%s: exit", __func__);
4366 pthread_mutex_unlock(&adev_init_lock);
4367 return 0;
4368 }
4369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 adev = calloc(1, sizeof(struct audio_device));
4371
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004372 if (!adev) {
4373 pthread_mutex_unlock(&adev_init_lock);
4374 return -ENOMEM;
4375 }
4376
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004377 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4380 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4381 adev->device.common.module = (struct hw_module_t *)module;
4382 adev->device.common.close = adev_close;
4383
4384 adev->device.init_check = adev_init_check;
4385 adev->device.set_voice_volume = adev_set_voice_volume;
4386 adev->device.set_master_volume = adev_set_master_volume;
4387 adev->device.get_master_volume = adev_get_master_volume;
4388 adev->device.set_master_mute = adev_set_master_mute;
4389 adev->device.get_master_mute = adev_get_master_mute;
4390 adev->device.set_mode = adev_set_mode;
4391 adev->device.set_mic_mute = adev_set_mic_mute;
4392 adev->device.get_mic_mute = adev_get_mic_mute;
4393 adev->device.set_parameters = adev_set_parameters;
4394 adev->device.get_parameters = adev_get_parameters;
4395 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4396 adev->device.open_output_stream = adev_open_output_stream;
4397 adev->device.close_output_stream = adev_close_output_stream;
4398 adev->device.open_input_stream = adev_open_input_stream;
4399 adev->device.close_input_stream = adev_close_input_stream;
4400 adev->device.dump = adev_dump;
4401
4402 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004404 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004405 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004407 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004408 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004409 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004410 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004411 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004412 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004413 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004414 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004415 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304416 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304417 adev->perf_lock_opts[0] = 0x101;
4418 adev->perf_lock_opts[1] = 0x20E;
4419 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304420
4421 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4422 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004424 adev->platform = platform_init(adev);
4425 if (!adev->platform) {
4426 free(adev->snd_dev_ref_cnt);
4427 free(adev);
4428 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4429 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004430 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004431 return -EINVAL;
4432 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004433
Naresh Tanniru4c630392014-05-12 01:05:52 +05304434 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4435
Eric Laurentc4aef752013-09-12 17:45:53 -07004436 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4437 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4438 if (adev->visualizer_lib == NULL) {
4439 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4440 } else {
4441 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4442 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004443 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004444 "visualizer_hal_start_output");
4445 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004446 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004447 "visualizer_hal_stop_output");
4448 }
4449 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004450 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004451 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004452
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004453 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4454 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4455 if (adev->offload_effects_lib == NULL) {
4456 ALOGE("%s: DLOPEN failed for %s", __func__,
4457 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4458 } else {
4459 ALOGV("%s: DLOPEN successful for %s", __func__,
4460 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4461 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304462 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004463 "offload_effects_bundle_hal_start_output");
4464 adev->offload_effects_stop_output =
4465 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4466 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004467 adev->offload_effects_set_hpx_state =
4468 (int (*)(bool))dlsym(adev->offload_effects_lib,
4469 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304470 adev->offload_effects_get_parameters =
4471 (void (*)(struct str_parms *, struct str_parms *))
4472 dlsym(adev->offload_effects_lib,
4473 "offload_effects_bundle_get_parameters");
4474 adev->offload_effects_set_parameters =
4475 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4476 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004477 }
4478 }
4479
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004480 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4481 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4482 if (adev->adm_lib == NULL) {
4483 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4484 } else {
4485 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4486 adev->adm_init = (adm_init_t)
4487 dlsym(adev->adm_lib, "adm_init");
4488 adev->adm_deinit = (adm_deinit_t)
4489 dlsym(adev->adm_lib, "adm_deinit");
4490 adev->adm_register_input_stream = (adm_register_input_stream_t)
4491 dlsym(adev->adm_lib, "adm_register_input_stream");
4492 adev->adm_register_output_stream = (adm_register_output_stream_t)
4493 dlsym(adev->adm_lib, "adm_register_output_stream");
4494 adev->adm_deregister_stream = (adm_deregister_stream_t)
4495 dlsym(adev->adm_lib, "adm_deregister_stream");
4496 adev->adm_request_focus = (adm_request_focus_t)
4497 dlsym(adev->adm_lib, "adm_request_focus");
4498 adev->adm_abandon_focus = (adm_abandon_focus_t)
4499 dlsym(adev->adm_lib, "adm_abandon_focus");
4500 }
4501 }
4502
Mingming Yin514a8bc2014-07-29 15:22:21 -07004503 adev->bt_wb_speech_enabled = false;
4504
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004505 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506 *device = &adev->device.common;
4507
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004508 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4509 &adev->streams_output_cfg_list);
4510
Kiran Kandi910e1862013-10-29 13:29:42 -07004511 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004512
4513 char value[PROPERTY_VALUE_MAX];
4514 int trial;
4515 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4516 trial = atoi(value);
4517 if (period_size_is_plausible_for_low_latency(trial)) {
4518 pcm_config_low_latency.period_size = trial;
4519 pcm_config_low_latency.start_threshold = trial / 4;
4520 pcm_config_low_latency.avail_min = trial / 4;
4521 configured_low_latency_capture_period_size = trial;
4522 }
4523 }
4524 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4525 trial = atoi(value);
4526 if (period_size_is_plausible_for_low_latency(trial)) {
4527 configured_low_latency_capture_period_size = trial;
4528 }
4529 }
4530
vivek mehta446c3962015-09-14 10:57:35 -07004531 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004532 pthread_mutex_unlock(&adev_init_lock);
4533
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004534 if (adev->adm_init)
4535 adev->adm_data = adev->adm_init();
4536
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304537 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004538 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539 return 0;
4540}
4541
4542static struct hw_module_methods_t hal_module_methods = {
4543 .open = adev_open,
4544};
4545
4546struct audio_module HAL_MODULE_INFO_SYM = {
4547 .common = {
4548 .tag = HARDWARE_MODULE_TAG,
4549 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4550 .hal_api_version = HARDWARE_HAL_API_VERSION,
4551 .id = AUDIO_HARDWARE_MODULE_ID,
4552 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004553 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004554 .methods = &hal_module_methods,
4555 },
4556};