blob: a8ebb6b6ce327d4d058f4da16a78186978c920c4 [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) ||
kunleiz303ff1a2016-03-15 17:40:20 +0800811 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_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)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302142 return out->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
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002188 if (is_offload_usecase(out->usecase))
2189 stop_compressed_output_l(out);
2190
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002191 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002193 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194 if (out->pcm) {
2195 pcm_close(out->pcm);
2196 out->pcm = NULL;
2197 }
2198 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002199 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302200 out->send_next_track_params = false;
2201 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002202 out->gapless_mdata.encoder_delay = 0;
2203 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204 if (out->compr != NULL) {
2205 compress_close(out->compr);
2206 out->compr = NULL;
2207 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002210 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 }
2212 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302213 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 return 0;
2215}
2216
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002217static int out_dump(const struct audio_stream *stream __unused,
2218 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219{
2220 return 0;
2221}
2222
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002223static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2224{
2225 int ret = 0;
2226 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002227
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002229 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002230 return -EINVAL;
2231 }
2232
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302233 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002234
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002235 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2236 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302237 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002238 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002239 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2240 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302241 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002242 }
2243
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002244 ALOGV("%s new encoder delay %u and padding %u", __func__,
2245 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2246
2247 return 0;
2248}
2249
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002250static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2251{
2252 return out == adev->primary_output || out == adev->voice_tx_output;
2253}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2256{
2257 struct stream_out *out = (struct stream_out *)stream;
2258 struct audio_device *adev = out->dev;
2259 struct str_parms *parms;
2260 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002261 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262
sangwoobc677242013-08-08 16:53:43 +09002263 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002264 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302266 if (!parms)
2267 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002268 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2269 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002271 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002272 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002274 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002275 * When HDMI cable is unplugged the music playback is paused and
2276 * the policy manager sends routing=0. But the audioflinger continues
2277 * to write data until standby time (3sec). As the HDMI core is
2278 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002279 * Avoid this by routing audio to speaker until standby.
2280 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002281 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2282 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302283 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002284 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2285 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002286 }
2287
2288 /*
2289 * select_devices() call below switches all the usecases on the same
2290 * backend to the new device. Refer to check_usecases_codec_backend() in
2291 * the select_devices(). But how do we undo this?
2292 *
2293 * For example, music playback is active on headset (deep-buffer usecase)
2294 * and if we go to ringtones and select a ringtone, low-latency usecase
2295 * will be started on headset+speaker. As we can't enable headset+speaker
2296 * and headset devices at the same time, select_devices() switches the music
2297 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2298 * So when the ringtone playback is completed, how do we undo the same?
2299 *
2300 * We are relying on the out_set_parameters() call on deep-buffer output,
2301 * once the ringtone playback is ended.
2302 * NOTE: We should not check if the current devices are same as new devices.
2303 * Because select_devices() must be called to switch back the music
2304 * playback to headset.
2305 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002306 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 out->devices = val;
2308
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302309 if (!out->standby) {
2310 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2311 adev->perf_lock_opts,
2312 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002313 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302314 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2315 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002316
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002317 if (output_drives_call(adev, out)) {
2318 if(!voice_is_in_call(adev)) {
2319 if (adev->mode == AUDIO_MODE_IN_CALL) {
2320 adev->current_call_output = out;
2321 ret = voice_start_call(adev);
2322 }
2323 } else {
2324 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002325 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002326 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002327 }
2328 }
2329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002331 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002333
2334 if (out == adev->primary_output) {
2335 pthread_mutex_lock(&adev->lock);
2336 audio_extn_set_parameters(adev, parms);
2337 pthread_mutex_unlock(&adev->lock);
2338 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002339 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002340 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002341 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002342
2343 audio_extn_dts_create_state_notifier_node(out->usecase);
2344 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2345 popcount(out->channel_mask),
2346 out->playback_started);
2347
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002348 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002349 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002350
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302352error:
Eric Laurent994a6932013-07-17 11:51:42 -07002353 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 return ret;
2355}
2356
2357static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2358{
2359 struct stream_out *out = (struct stream_out *)stream;
2360 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002361 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 char value[256];
2363 struct str_parms *reply = str_parms_create();
2364 size_t i, j;
2365 int ret;
2366 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002367
2368 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002369 if (reply) {
2370 str_parms_destroy(reply);
2371 }
2372 if (query) {
2373 str_parms_destroy(query);
2374 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002375 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2376 return NULL;
2377 }
2378
Eric Laurent994a6932013-07-17 11:51:42 -07002379 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2381 if (ret >= 0) {
2382 value[0] = '\0';
2383 i = 0;
2384 while (out->supported_channel_masks[i] != 0) {
2385 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2386 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2387 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002388 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002390 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 first = false;
2392 break;
2393 }
2394 }
2395 i++;
2396 }
2397 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2398 str = str_parms_to_str(reply);
2399 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002400 voice_extn_out_get_parameters(out, query, reply);
2401 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002402 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002403 free(str);
2404 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002407
Alexy Joseph62142aa2015-11-16 15:10:34 -08002408
2409 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2410 if (ret >= 0) {
2411 value[0] = '\0';
2412 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2413 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302414 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002415 } else {
2416 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302417 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002418 }
2419 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002420 if (str)
2421 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002422 str = str_parms_to_str(reply);
2423 }
2424
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002425 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2426 if (ret >= 0) {
2427 value[0] = '\0';
2428 i = 0;
2429 first = true;
2430 while (out->supported_formats[i] != 0) {
2431 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2432 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2433 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002434 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002435 }
2436 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2437 first = false;
2438 break;
2439 }
2440 }
2441 i++;
2442 }
2443 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002444 if (str)
2445 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002446 str = str_parms_to_str(reply);
2447 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002448
2449 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2450 if (ret >= 0) {
2451 value[0] = '\0';
2452 i = 0;
2453 first = true;
2454 while (out->supported_sample_rates[i] != 0) {
2455 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2456 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2457 if (!first) {
2458 strlcat(value, "|", sizeof(value));
2459 }
2460 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2461 first = false;
2462 break;
2463 }
2464 }
2465 i++;
2466 }
2467 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2468 if (str)
2469 free(str);
2470 str = str_parms_to_str(reply);
2471 }
2472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 str_parms_destroy(query);
2474 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002475 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 return str;
2477}
2478
2479static uint32_t out_get_latency(const struct audio_stream_out *stream)
2480{
2481 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002482 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483
Alexy Josephaa54c872014-12-03 02:46:47 -08002484 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002485 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002486 } else {
2487 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002489 }
2490
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302491 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002492 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493}
2494
2495static int out_set_volume(struct audio_stream_out *stream, float left,
2496 float right)
2497{
Eric Laurenta9024de2013-04-04 09:19:12 -07002498 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 int volume[2];
2500
Eric Laurenta9024de2013-04-04 09:19:12 -07002501 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2502 /* only take left channel into account: the API is for stereo anyway */
2503 out->muted = (left == 0.0f);
2504 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002505 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302506 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002507 /*
2508 * Set mute or umute on HDMI passthrough stream.
2509 * Only take left channel into account.
2510 * Mute is 0 and unmute 1
2511 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302512 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002513 } else {
2514 char mixer_ctl_name[128];
2515 struct audio_device *adev = out->dev;
2516 struct mixer_ctl *ctl;
2517 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002518 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002519
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002520 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2521 "Compress Playback %d Volume", pcm_device_id);
2522 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2523 if (!ctl) {
2524 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2525 __func__, mixer_ctl_name);
2526 return -EINVAL;
2527 }
2528 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2529 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2530 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2531 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002533 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 return -ENOSYS;
2536}
2537
2538static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2539 size_t bytes)
2540{
2541 struct stream_out *out = (struct stream_out *)stream;
2542 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302543 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002544 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002546 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302547
Naresh Tanniru80659832014-06-04 18:17:56 +05302548 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002549
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302550 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302551 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302552 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2553 pthread_mutex_unlock(&out->lock);
2554 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302555 } else {
2556 /* increase written size during SSR to avoid mismatch
2557 * with the written frames count in AF
2558 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302559 if (audio_bytes_per_sample(out->format) != 0)
2560 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302561 ALOGD(" %s: sound card is not active/SSR state", __func__);
2562 ret= -EIO;
2563 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302564 }
2565 }
2566
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302567 if (audio_extn_passthru_should_drop_data(out)) {
2568 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2569 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2570 out_get_sample_rate(&out->stream.common));
2571 goto exit;
2572 }
2573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002575 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002576 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2578 ret = voice_extn_compress_voip_start_output_stream(out);
2579 else
2580 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002581 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002584 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 goto exit;
2586 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002587
2588 if (last_known_cal_step != -1) {
2589 ALOGD("%s: retry previous failed cal level set", __func__);
2590 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2591 }
2592
vivek mehta446c3962015-09-14 10:57:35 -07002593 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002594 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596
Ashish Jain81eb2a82015-05-13 10:52:34 +05302597 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002598 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302599 adev->is_channel_status_set = true;
2600 }
2601
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002602 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002603 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002604 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002605 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002606 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2607 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302608 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2609 ALOGD("copl(%p):send next track params in gapless", out);
2610 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2611 out->send_next_track_params = false;
2612 out->is_compr_metadata_avail = false;
2613 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002614 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302615 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302616 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002617
Ashish Jain83a6cc22016-06-28 14:34:17 +05302618 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302619 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302620 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302621 pthread_mutex_unlock(&out->lock);
2622 return -EINVAL;
2623 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302624 audio_format_t dst_format = out->hal_op_format;
2625 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302626
2627 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2628 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2629
Ashish Jain83a6cc22016-06-28 14:34:17 +05302630 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302631 dst_format,
2632 buffer,
2633 src_format,
2634 frames);
2635
Ashish Jain83a6cc22016-06-28 14:34:17 +05302636 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302637 bytes_to_write);
2638
2639 /*Convert written bytes in audio flinger format*/
2640 if (ret > 0)
2641 ret = ((ret * format_to_bitwidth_table[out->format]) /
2642 format_to_bitwidth_table[dst_format]);
2643 }
2644 } else
2645 ret = compress_write(out->compr, buffer, bytes);
2646
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302647 if (ret < 0)
2648 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302649 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002650 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302651 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302653 } else if (-ENETRESET == ret) {
2654 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2655 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2656 pthread_mutex_unlock(&out->lock);
2657 out_standby(&out->stream.common);
2658 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 }
Ashish Jain5106d362016-05-11 19:23:33 +05302660 if ( ret == (ssize_t)bytes && !out->non_blocking)
2661 out->written += bytes;
2662
Naresh Tanniru80659832014-06-04 18:17:56 +05302663 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002664 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002665 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002666 out->playback_started = 1;
2667 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002668
2669 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2670 popcount(out->channel_mask),
2671 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002672 }
2673 pthread_mutex_unlock(&out->lock);
2674 return ret;
2675 } else {
2676 if (out->pcm) {
2677 if (out->muted)
2678 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002679
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302680 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002681
2682 if (adev->adm_request_focus)
2683 adev->adm_request_focus(adev->adm_data, out->handle);
2684
Ashish Jain83a6cc22016-06-28 14:34:17 +05302685 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002686 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302687 } else if (out->hal_op_format != out->hal_ip_format &&
2688 out->convert_buffer != NULL) {
2689
2690 memcpy_by_audio_format(out->convert_buffer,
2691 out->hal_op_format,
2692 buffer,
2693 out->hal_ip_format,
2694 out->config.period_size * out->config.channels);
2695
2696 ret = pcm_write(out->pcm, out->convert_buffer,
2697 (out->config.period_size *
2698 out->config.channels *
2699 format_to_bitwidth_table[out->hal_op_format]));
2700 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002701 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302702 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002703
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302704 if (ret < 0)
2705 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302706 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2707 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2708 else
2709 ret = -EINVAL;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002710
2711 if (adev->adm_abandon_focus)
2712 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002713 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714 }
2715
2716exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302717 /* ToDo: There may be a corner case when SSR happens back to back during
2718 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302719 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302720 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302721 }
2722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723 pthread_mutex_unlock(&out->lock);
2724
2725 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002726 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002727 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302728 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302729 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302730 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302731 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302732 out->standby = true;
2733 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302735 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302736 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 }
2738 return bytes;
2739}
2740
2741static int out_get_render_position(const struct audio_stream_out *stream,
2742 uint32_t *dsp_frames)
2743{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302745 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002746
2747 if (dsp_frames == NULL)
2748 return -EINVAL;
2749
2750 *dsp_frames = 0;
2751 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002752 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302753
2754 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2755 * this operation and adev_close_output_stream(where out gets reset).
2756 */
2757 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2758 *dsp_frames = get_actual_pcm_frames_rendered(out);
2759 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2760 return 0;
2761 }
2762
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002763 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302764 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302765 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302767 if (ret < 0)
2768 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002769 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302770 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 }
2772 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302773 if (-ENETRESET == ret) {
2774 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2775 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2776 return -EINVAL;
2777 } else if(ret < 0) {
2778 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2779 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302780 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2781 /*
2782 * Handle corner case where compress session is closed during SSR
2783 * and timestamp is queried
2784 */
2785 ALOGE(" ERROR: sound card not active, return error");
2786 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302787 } else {
2788 return 0;
2789 }
Zhou Song32a556e2015-05-05 10:46:56 +08002790 } else if (audio_is_linear_pcm(out->format)) {
2791 *dsp_frames = out->written;
2792 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793 } else
2794 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795}
2796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002797static int out_add_audio_effect(const struct audio_stream *stream __unused,
2798 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799{
2800 return 0;
2801}
2802
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002803static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2804 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805{
2806 return 0;
2807}
2808
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002809static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2810 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811{
2812 return -EINVAL;
2813}
2814
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002815static int out_get_presentation_position(const struct audio_stream_out *stream,
2816 uint64_t *frames, struct timespec *timestamp)
2817{
2818 struct stream_out *out = (struct stream_out *)stream;
2819 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002820 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002821
Ashish Jain5106d362016-05-11 19:23:33 +05302822 /* below piece of code is not guarded against any lock because audioFliner serializes
2823 * this operation and adev_close_output_stream( where out gets reset).
2824 */
2825 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2826 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2827 *frames = get_actual_pcm_frames_rendered(out);
2828 /* this is the best we can do */
2829 clock_gettime(CLOCK_MONOTONIC, timestamp);
2830 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2831 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2832 return 0;
2833 }
2834
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002835 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002836
Ashish Jain5106d362016-05-11 19:23:33 +05302837 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2838 ret = compress_get_tstamp(out->compr, &dsp_frames,
2839 &out->sample_rate);
2840 ALOGVV("%s rendered frames %ld sample_rate %d",
2841 __func__, dsp_frames, out->sample_rate);
2842 *frames = dsp_frames;
2843 if (ret < 0)
2844 ret = -errno;
2845 if (-ENETRESET == ret) {
2846 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2847 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2848 ret = -EINVAL;
2849 } else
2850 ret = 0;
2851 /* this is the best we can do */
2852 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002853 } else {
2854 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002855 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002856 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2857 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002858 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002859 // This adjustment accounts for buffering after app processor.
2860 // It is based on estimated DSP latency per use case, rather than exact.
2861 signed_frames -=
2862 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2863
Eric Laurent949a0892013-09-20 09:20:13 -07002864 // It would be unusual for this value to be negative, but check just in case ...
2865 if (signed_frames >= 0) {
2866 *frames = signed_frames;
2867 ret = 0;
2868 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002869 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302870 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2871 *frames = out->written;
2872 clock_gettime(CLOCK_MONOTONIC, timestamp);
2873 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002874 }
2875 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002876 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002877 return ret;
2878}
2879
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880static int out_set_callback(struct audio_stream_out *stream,
2881 stream_callback_t callback, void *cookie)
2882{
2883 struct stream_out *out = (struct stream_out *)stream;
2884
2885 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002886 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 out->offload_callback = callback;
2888 out->offload_cookie = cookie;
2889 pthread_mutex_unlock(&out->lock);
2890 return 0;
2891}
2892
2893static int out_pause(struct audio_stream_out* stream)
2894{
2895 struct stream_out *out = (struct stream_out *)stream;
2896 int status = -ENOSYS;
2897 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002898 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002899 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002900 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302902 struct audio_device *adev = out->dev;
2903 int snd_scard_state = get_snd_card_state(adev);
2904
2905 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2906 status = compress_pause(out->compr);
2907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002909
Mingming Yin21854652016-04-13 11:54:02 -07002910 if (audio_extn_passthru_is_active()) {
2911 ALOGV("offload use case, pause passthru");
2912 audio_extn_passthru_on_pause(out);
2913 }
2914
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302915 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002916 audio_extn_dts_notify_playback_state(out->usecase, 0,
2917 out->sample_rate, popcount(out->channel_mask),
2918 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 }
2920 pthread_mutex_unlock(&out->lock);
2921 }
2922 return status;
2923}
2924
2925static int out_resume(struct audio_stream_out* stream)
2926{
2927 struct stream_out *out = (struct stream_out *)stream;
2928 int status = -ENOSYS;
2929 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002930 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002931 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002932 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002933 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002934 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302935 struct audio_device *adev = out->dev;
2936 int snd_scard_state = get_snd_card_state(adev);
2937
Mingming Yin21854652016-04-13 11:54:02 -07002938 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2939 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2940 pthread_mutex_lock(&out->dev->lock);
2941 ALOGV("offload resume, check and set hdmi backend again");
2942 check_and_set_hdmi_backend(out);
2943 pthread_mutex_unlock(&out->dev->lock);
2944 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302945 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002946 }
2947 if (!status) {
2948 out->offload_state = OFFLOAD_STATE_PLAYING;
2949 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302950 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002951 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2952 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 }
2954 pthread_mutex_unlock(&out->lock);
2955 }
2956 return status;
2957}
2958
2959static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2960{
2961 struct stream_out *out = (struct stream_out *)stream;
2962 int status = -ENOSYS;
2963 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002964 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002965 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002966 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2967 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2968 else
2969 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2970 pthread_mutex_unlock(&out->lock);
2971 }
2972 return status;
2973}
2974
2975static int out_flush(struct audio_stream_out* stream)
2976{
2977 struct stream_out *out = (struct stream_out *)stream;
2978 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002979 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002980 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002981 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302983 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002984 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002985 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986 return 0;
2987 }
2988 return -ENOSYS;
2989}
2990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991/** audio_stream_in implementation **/
2992static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2993{
2994 struct stream_in *in = (struct stream_in *)stream;
2995
2996 return in->config.rate;
2997}
2998
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002999static int in_set_sample_rate(struct audio_stream *stream __unused,
3000 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001{
3002 return -ENOSYS;
3003}
3004
3005static size_t in_get_buffer_size(const struct audio_stream *stream)
3006{
3007 struct stream_in *in = (struct stream_in *)stream;
3008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003009 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3010 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003011 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3012 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003013
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003014 return in->config.period_size *
3015 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016}
3017
3018static uint32_t in_get_channels(const struct audio_stream *stream)
3019{
3020 struct stream_in *in = (struct stream_in *)stream;
3021
3022 return in->channel_mask;
3023}
3024
3025static audio_format_t in_get_format(const struct audio_stream *stream)
3026{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003027 struct stream_in *in = (struct stream_in *)stream;
3028
3029 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030}
3031
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003032static int in_set_format(struct audio_stream *stream __unused,
3033 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
3035 return -ENOSYS;
3036}
3037
3038static int in_standby(struct audio_stream *stream)
3039{
3040 struct stream_in *in = (struct stream_in *)stream;
3041 struct audio_device *adev = in->dev;
3042 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303043 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3044 stream, in->usecase, use_case_table[in->usecase]);
3045
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003046 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3047 /* Ignore standby in case of voip call because the voip input
3048 * stream is closed in adev_close_input_stream()
3049 */
3050 ALOGV("%s: Ignore Standby in VOIP call", __func__);
3051 return status;
3052 }
3053
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003054 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003055 if (!in->standby && in->is_st_session) {
3056 ALOGD("%s: sound trigger pcm stop lab", __func__);
3057 audio_extn_sound_trigger_stop_lab(in);
3058 in->standby = 1;
3059 }
3060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003062 if (adev->adm_deregister_stream)
3063 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3064
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003065 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003067 if (in->pcm) {
3068 pcm_close(in->pcm);
3069 in->pcm = NULL;
3070 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003072 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 }
3074 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003075 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 return status;
3077}
3078
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003079static int in_dump(const struct audio_stream *stream __unused,
3080 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081{
3082 return 0;
3083}
3084
3085static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3086{
3087 struct stream_in *in = (struct stream_in *)stream;
3088 struct audio_device *adev = in->dev;
3089 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003091 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303093 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 parms = str_parms_create_str(kvpairs);
3095
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303096 if (!parms)
3097 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003098 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003099 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003100
3101 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3102 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 val = atoi(value);
3104 /* no audio source uses val == 0 */
3105 if ((in->source != val) && (val != 0)) {
3106 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003107 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3108 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3109 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003110 (in->config.rate == 8000 || in->config.rate == 16000 ||
3111 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003112 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003113 err = voice_extn_compress_voip_open_input_stream(in);
3114 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003115 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003116 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003117 }
3118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119 }
3120 }
3121
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003122 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3123 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003125 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 in->device = val;
3127 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003128 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003129 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 }
3131 }
3132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003134 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135
3136 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303137error:
Eric Laurent994a6932013-07-17 11:51:42 -07003138 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 return ret;
3140}
3141
3142static char* in_get_parameters(const struct audio_stream *stream,
3143 const char *keys)
3144{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003145 struct stream_in *in = (struct stream_in *)stream;
3146 struct str_parms *query = str_parms_create_str(keys);
3147 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003148 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003149
3150 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003151 if (reply) {
3152 str_parms_destroy(reply);
3153 }
3154 if (query) {
3155 str_parms_destroy(query);
3156 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003157 ALOGE("in_get_parameters: failed to create query or reply");
3158 return NULL;
3159 }
3160
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003161 ALOGV("%s: enter: keys - %s", __func__, keys);
3162
3163 voice_extn_in_get_parameters(in, query, reply);
3164
3165 str = str_parms_to_str(reply);
3166 str_parms_destroy(query);
3167 str_parms_destroy(reply);
3168
3169 ALOGV("%s: exit: returns - %s", __func__, str);
3170 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171}
3172
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003173static int in_set_gain(struct audio_stream_in *stream __unused,
3174 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175{
3176 return 0;
3177}
3178
3179static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3180 size_t bytes)
3181{
3182 struct stream_in *in = (struct stream_in *)stream;
3183 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303184 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303185 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303186 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003188 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303189
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003190 if (in->is_st_session) {
3191 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3192 /* Read from sound trigger HAL */
3193 audio_extn_sound_trigger_read(in, buffer, bytes);
3194 pthread_mutex_unlock(&in->lock);
3195 return bytes;
3196 }
3197
Ashish Jainbbce4322016-02-16 13:25:27 +05303198 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003199 ALOGD(" %s: sound card is not active/SSR state", __func__);
3200 ret= -EIO;;
3201 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303202 }
3203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003205 pthread_mutex_lock(&adev->lock);
3206 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3207 ret = voice_extn_compress_voip_start_input_stream(in);
3208 else
3209 ret = start_input_stream(in);
3210 pthread_mutex_unlock(&adev->lock);
3211 if (ret != 0) {
3212 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 }
3214 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003215 if (adev->adm_register_input_stream)
3216 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003219 if (adev->adm_request_focus)
3220 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303223 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003224 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303225 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003226 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303227 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003228 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303229 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003230 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303231 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3232 if (bytes % 4 == 0) {
3233 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3234 int_buf_stream = buffer;
3235 for (size_t itt=0; itt < bytes/4 ; itt++) {
3236 int_buf_stream[itt] >>= 8;
3237 }
3238 } else {
3239 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3240 ret = -EINVAL;
3241 goto exit;
3242 }
3243 } if (ret < 0) {
3244 ret = -errno;
3245 }
3246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 }
3248
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003249 if (adev->adm_abandon_focus)
3250 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 /*
3253 * Instead of writing zeroes here, we could trust the hardware
3254 * to always provide zeroes when muted.
3255 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303256 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3257 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 memset(buffer, 0, bytes);
3259
3260exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303261 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303262 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003263 if (-ENETRESET == ret)
3264 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 pthread_mutex_unlock(&in->lock);
3267
3268 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303269 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303270 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303271 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303272 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303273 in->standby = true;
3274 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303275 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003277 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303278 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303279 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 }
3281 return bytes;
3282}
3283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003284static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285{
3286 return 0;
3287}
3288
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003289static int add_remove_audio_effect(const struct audio_stream *stream,
3290 effect_handle_t effect,
3291 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003293 struct stream_in *in = (struct stream_in *)stream;
3294 int status = 0;
3295 effect_descriptor_t desc;
3296
3297 status = (*effect)->get_descriptor(effect, &desc);
3298 if (status != 0)
3299 return status;
3300
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003301 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003302 pthread_mutex_lock(&in->dev->lock);
3303 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3304 in->enable_aec != enable &&
3305 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3306 in->enable_aec = enable;
3307 if (!in->standby)
3308 select_devices(in->dev, in->usecase);
3309 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003310 if (in->enable_ns != enable &&
3311 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3312 in->enable_ns = enable;
3313 if (!in->standby)
3314 select_devices(in->dev, in->usecase);
3315 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003316 pthread_mutex_unlock(&in->dev->lock);
3317 pthread_mutex_unlock(&in->lock);
3318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 return 0;
3320}
3321
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003322static int in_add_audio_effect(const struct audio_stream *stream,
3323 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324{
Eric Laurent994a6932013-07-17 11:51:42 -07003325 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003326 return add_remove_audio_effect(stream, effect, true);
3327}
3328
3329static int in_remove_audio_effect(const struct audio_stream *stream,
3330 effect_handle_t effect)
3331{
Eric Laurent994a6932013-07-17 11:51:42 -07003332 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003333 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334}
3335
3336static int adev_open_output_stream(struct audio_hw_device *dev,
3337 audio_io_handle_t handle,
3338 audio_devices_t devices,
3339 audio_output_flags_t flags,
3340 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003341 struct audio_stream_out **stream_out,
3342 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 struct audio_device *adev = (struct audio_device *)dev;
3345 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303346 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003347 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303350
3351 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3352 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003353 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303354 return -EINVAL;
3355 }
3356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3358
Mingming Yin3a941d42016-02-17 18:08:05 -08003359 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3360 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303361 devices, flags, &out->stream);
3362
3363
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003364 if (!out) {
3365 return -ENOMEM;
3366 }
3367
Haynes Mathew George204045b2015-02-25 20:32:03 -08003368 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003369 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003370 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 if (devices == AUDIO_DEVICE_NONE)
3373 devices = AUDIO_DEVICE_OUT_SPEAKER;
3374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 out->flags = flags;
3376 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003377 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003378 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 out->sample_rate = config->sample_rate;
3380 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3381 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003382 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003383 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003384 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303385 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386
Mingming Yin3a941d42016-02-17 18:08:05 -08003387 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3388 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3389 pthread_mutex_lock(&adev->lock);
3390 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3391 ret = read_hdmi_sink_caps(out);
3392 pthread_mutex_unlock(&adev->lock);
3393 if (ret != 0) {
3394 if (ret == -ENOSYS) {
3395 /* ignore and go with default */
3396 ret = 0;
3397 } else {
3398 ALOGE("error reading hdmi sink caps");
3399 goto error_open;
3400 }
3401 }
3402 }
3403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003405 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303406 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3407 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003408 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3409 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3410
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003411 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003412 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3413 /*
3414 * Do not handle stereo output in Multi-channel cases
3415 * Stereo case is handled in normal playback path
3416 */
3417 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3418 ret = AUDIO_CHANNEL_OUT_STEREO;
3419 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003420
3421 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3422 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003423 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003424 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003425 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003426
3427 if (config->sample_rate == 0)
3428 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3429 if (config->channel_mask == 0)
3430 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003431 if (config->format == 0)
3432 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003433
3434 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003436 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3438 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003440 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003442 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3443 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003444 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003445 ret = voice_extn_compress_voip_open_output_stream(out);
3446 if (ret != 0) {
3447 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3448 __func__, ret);
3449 goto error_open;
3450 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003451 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3452 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3453
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003454 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3455 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3456 ALOGE("%s: Unsupported Offload information", __func__);
3457 ret = -EINVAL;
3458 goto error_open;
3459 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003460
Mingming Yin3a941d42016-02-17 18:08:05 -08003461 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003462 if(config->offload_info.format == 0)
3463 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003464 if (config->offload_info.sample_rate == 0)
3465 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003466 }
3467
Mingming Yin90310102013-11-13 16:57:00 -08003468 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303469 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003470 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 ret = -EINVAL;
3472 goto error_open;
3473 }
3474
3475 out->compr_config.codec = (struct snd_codec *)
3476 calloc(1, sizeof(struct snd_codec));
3477
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003478 if (!out->compr_config.codec) {
3479 ret = -ENOMEM;
3480 goto error_open;
3481 }
3482
vivek mehta0ea887a2015-08-26 14:01:20 -07003483 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303484 out->stream.pause = out_pause;
3485 out->stream.flush = out_flush;
3486 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003487 out->usecase = get_offload_usecase(adev, true);
3488 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003489 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003490 out->stream.set_callback = out_set_callback;
3491 out->stream.pause = out_pause;
3492 out->stream.resume = out_resume;
3493 out->stream.drain = out_drain;
3494 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003495 out->usecase = get_offload_usecase(adev, false);
3496 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003497 }
vivek mehta446c3962015-09-14 10:57:35 -07003498
3499 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003500 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3501 config->format == 0 && config->sample_rate == 0 &&
3502 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003503 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003504 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3505 } else {
3506 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3507 ret = -EEXIST;
3508 goto error_open;
3509 }
vivek mehta446c3962015-09-14 10:57:35 -07003510 }
3511
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 if (config->offload_info.channel_mask)
3513 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003514 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003515 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003516 config->offload_info.channel_mask = config->channel_mask;
3517 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003518 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 out->sample_rate = config->offload_info.sample_rate;
3520
Mingming Yin3ee55c62014-08-04 14:23:35 -07003521 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303523 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3524 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3525 audio_extn_dolby_send_ddp_endp_params(adev);
3526 audio_extn_dolby_set_dmid(adev);
3527 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003529 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003530 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003531 out->compr_config.codec->bit_rate =
3532 config->offload_info.bit_rate;
3533 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003534 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003535 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303536 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003537 /*TODO: Do we need to change it for passthrough */
3538 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003539
Manish Dewangana6fc5442015-08-24 20:30:31 +05303540 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3541 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3542 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3543 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303544
3545 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3546 AUDIO_FORMAT_PCM) {
3547
3548 /*Based on platform support, configure appropriate alsa format for corresponding
3549 *hal input format.
3550 */
3551 out->compr_config.codec->format = hal_format_to_alsa(
3552 config->offload_info.format);
3553
Ashish Jain83a6cc22016-06-28 14:34:17 +05303554 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303555 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303556 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303557
3558 /*for direct PCM playback populate bit_width based on selected alsa format as
3559 *hal input format and alsa format might differ based on platform support.
3560 */
3561 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303562 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303563
3564 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3565
3566 /* Check if alsa session is configured with the same format as HAL input format,
3567 * if not then derive correct fragment size needed to accomodate the
3568 * conversion of HAL input format to alsa format.
3569 */
3570 audio_extn_utils_update_direct_pcm_fragment_size(out);
3571
3572 /*if hal input and output fragment size is different this indicates HAL input format is
3573 *not same as the alsa format
3574 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303575 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303576 /*Allocate a buffer to convert input data to the alsa configured format.
3577 *size of convert buffer is equal to the size required to hold one fragment size
3578 *worth of pcm data, this is because flinger does not write more than fragment_size
3579 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303580 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3581 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303582 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3583 ret = -ENOMEM;
3584 goto error_open;
3585 }
3586 }
3587 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3588 out->compr_config.fragment_size =
3589 audio_extn_passthru_get_buffer_size(&config->offload_info);
3590 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3591 } else {
3592 out->compr_config.fragment_size =
3593 platform_get_compress_offload_buffer_size(&config->offload_info);
3594 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3595 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003596
Amit Shekhar6f461b12014-08-01 14:52:58 -07003597 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303598 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003599
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003600 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3601 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003602
Alexy Josephaa54c872014-12-03 02:46:47 -08003603
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003604 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303605 out->send_next_track_params = false;
3606 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003607 out->offload_state = OFFLOAD_STATE_IDLE;
3608 out->playback_started = 0;
3609
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003610 audio_extn_dts_create_state_notifier_node(out->usecase);
3611
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003612 create_offload_callback_thread(out);
3613 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3614 __func__, config->offload_info.version,
3615 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303616
3617 /* Disable gapless if any of the following is true
3618 * passthrough playback
3619 * AV playback
3620 * Direct PCM playback
3621 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303622 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303623 config->offload_info.has_video ||
3624 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3625 check_and_set_gapless_mode(adev, false);
3626 } else
3627 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003628
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303629 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003630 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3631 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003632 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303633 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003634 if (ret != 0) {
3635 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3636 __func__, ret);
3637 goto error_open;
3638 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003639 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3640 if (config->sample_rate == 0)
3641 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3642 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3643 config->sample_rate != 8000) {
3644 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3645 ret = -EINVAL;
3646 goto error_open;
3647 }
3648 out->sample_rate = config->sample_rate;
3649 out->config.rate = config->sample_rate;
3650 if (config->format == AUDIO_FORMAT_DEFAULT)
3651 config->format = AUDIO_FORMAT_PCM_16_BIT;
3652 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3653 config->format = AUDIO_FORMAT_PCM_16_BIT;
3654 ret = -EINVAL;
3655 goto error_open;
3656 }
3657 out->format = config->format;
3658 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3659 out->config = pcm_config_afe_proxy_playback;
3660 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003661 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303662 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3663 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3664 out->config = pcm_config_low_latency;
3665 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3666 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3667 out->config = pcm_config_low_latency;
3668 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3669 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3670 out->config = pcm_config_deep_buffer;
3671 } else {
3672 /* primary path is the default path selected if no other outputs are available/suitable */
3673 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3674 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3675 }
3676 out->hal_ip_format = format = out->format;
3677 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3678 out->hal_op_format = pcm_format_to_hal(out->config.format);
3679 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3680 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003681 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303682 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3683 if (out->hal_ip_format != out->hal_op_format) {
3684 uint32_t buffer_size = out->config.period_size *
3685 format_to_bitwidth_table[out->hal_op_format] *
3686 out->config.channels;
3687 out->convert_buffer = calloc(1, buffer_size);
3688 if (out->convert_buffer == NULL){
3689 ALOGE("Allocation failed for convert buffer for size %d",
3690 out->compr_config.fragment_size);
3691 ret = -ENOMEM;
3692 goto error_open;
3693 }
3694 ALOGD("Convert buffer allocated of size %d", buffer_size);
3695 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 }
3697
Ashish Jain83a6cc22016-06-28 14:34:17 +05303698 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3699 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3700
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003701 /* TODO remove this hardcoding and check why width is zero*/
3702 if (out->bit_width == 0)
3703 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003704 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3705 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003706 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303707 out->bit_width, out->channel_mask,
3708 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003709 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3710 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3711 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003712 if(adev->primary_output == NULL)
3713 adev->primary_output = out;
3714 else {
3715 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003716 ret = -EEXIST;
3717 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003718 }
3719 }
3720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 /* Check if this usecase is already existing */
3722 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003723 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3724 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003727 ret = -EEXIST;
3728 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 }
3730 pthread_mutex_unlock(&adev->lock);
3731
3732 out->stream.common.get_sample_rate = out_get_sample_rate;
3733 out->stream.common.set_sample_rate = out_set_sample_rate;
3734 out->stream.common.get_buffer_size = out_get_buffer_size;
3735 out->stream.common.get_channels = out_get_channels;
3736 out->stream.common.get_format = out_get_format;
3737 out->stream.common.set_format = out_set_format;
3738 out->stream.common.standby = out_standby;
3739 out->stream.common.dump = out_dump;
3740 out->stream.common.set_parameters = out_set_parameters;
3741 out->stream.common.get_parameters = out_get_parameters;
3742 out->stream.common.add_audio_effect = out_add_audio_effect;
3743 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3744 out->stream.get_latency = out_get_latency;
3745 out->stream.set_volume = out_set_volume;
3746 out->stream.write = out_write;
3747 out->stream.get_render_position = out_get_render_position;
3748 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003749 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003752 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003753 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754
3755 config->format = out->stream.common.get_format(&out->stream.common);
3756 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3757 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3758
3759 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303760 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003761 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003762
3763 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3764 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3765 popcount(out->channel_mask), out->playback_started);
3766
Eric Laurent994a6932013-07-17 11:51:42 -07003767 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003769
3770error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303771 if (out->convert_buffer)
3772 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003773 free(out);
3774 *stream_out = NULL;
3775 ALOGD("%s: exit: ret %d", __func__, ret);
3776 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777}
3778
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003779static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 struct audio_stream_out *stream)
3781{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003782 struct stream_out *out = (struct stream_out *)stream;
3783 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003784 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003785
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303786 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3787
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003788 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303789 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003790 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303791 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003792 if(ret != 0)
3793 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3794 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003795 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003796 out_standby(&stream->common);
3797
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003798 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003799 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003801 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802 if (out->compr_config.codec != NULL)
3803 free(out->compr_config.codec);
3804 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003805
Ashish Jain83a6cc22016-06-28 14:34:17 +05303806 if (out->convert_buffer != NULL) {
3807 free(out->convert_buffer);
3808 out->convert_buffer = NULL;
3809 }
3810
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003811 if (adev->voice_tx_output == out)
3812 adev->voice_tx_output = NULL;
3813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 pthread_cond_destroy(&out->cond);
3815 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003817 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818}
3819
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003820static void close_compress_sessions(struct audio_device *adev)
3821{
Mingming Yin7b762e72015-03-04 13:47:32 -08003822 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303823 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003824 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003825 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303826
3827 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003828 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303829 if (is_offload_usecase(usecase->id)) {
3830 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003831 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3832 out = usecase->stream.out;
3833 pthread_mutex_unlock(&adev->lock);
3834 out_standby(&out->stream.common);
3835 pthread_mutex_lock(&adev->lock);
3836 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303837 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003838 }
3839 pthread_mutex_unlock(&adev->lock);
3840}
3841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3843{
3844 struct audio_device *adev = (struct audio_device *)dev;
3845 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003847 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003848 int ret;
3849 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003851 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303854 if (!parms)
3855 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003856 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3857 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303858 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303859 if (strstr(snd_card_status, "OFFLINE")) {
3860 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303861 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003862 //close compress sessions on OFFLINE status
3863 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303864 } else if (strstr(snd_card_status, "ONLINE")) {
3865 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303866 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003867 //send dts hpx license if enabled
3868 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303869 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303870 }
3871
3872 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003873 status = voice_set_parameters(adev, parms);
3874 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003875 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003877 status = platform_set_parameters(adev->platform, parms);
3878 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003879 goto done;
3880
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003881 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3882 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003883 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3885 adev->bluetooth_nrec = true;
3886 else
3887 adev->bluetooth_nrec = false;
3888 }
3889
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003890 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3891 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3893 adev->screen_off = false;
3894 else
3895 adev->screen_off = true;
3896 }
3897
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003898 ret = str_parms_get_int(parms, "rotation", &val);
3899 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003900 bool reverse_speakers = false;
3901 switch(val) {
3902 // FIXME: note that the code below assumes that the speakers are in the correct placement
3903 // relative to the user when the device is rotated 90deg from its default rotation. This
3904 // assumption is device-specific, not platform-specific like this code.
3905 case 270:
3906 reverse_speakers = true;
3907 break;
3908 case 0:
3909 case 90:
3910 case 180:
3911 break;
3912 default:
3913 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003914 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003915 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003916 if (status == 0) {
3917 if (adev->speaker_lr_swap != reverse_speakers) {
3918 adev->speaker_lr_swap = reverse_speakers;
3919 // only update the selected device if there is active pcm playback
3920 struct audio_usecase *usecase;
3921 struct listnode *node;
3922 list_for_each(node, &adev->usecase_list) {
3923 usecase = node_to_item(node, struct audio_usecase, list);
3924 if (usecase->type == PCM_PLAYBACK) {
3925 select_devices(adev, usecase->id);
3926 break;
3927 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003928 }
3929 }
3930 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003931 }
3932
Mingming Yin514a8bc2014-07-29 15:22:21 -07003933 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3934 if (ret >= 0) {
3935 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3936 adev->bt_wb_speech_enabled = true;
3937 else
3938 adev->bt_wb_speech_enabled = false;
3939 }
3940
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003941 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3942 if (ret >= 0) {
3943 val = atoi(value);
3944 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3945 ALOGV("cache new edid");
3946 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003947 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3948 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07003949 /*
3950 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3951 * Per AudioPolicyManager, USB device is higher priority than WFD.
3952 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3953 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3954 * starting voice call on USB
3955 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003956 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3957 if (ret >= 0) {
3958 audio_extn_usb_add_device(val, atoi(value));
3959 }
vivek mehta344576a2016-04-12 18:56:03 -07003960 ALOGV("detected USB connect .. disable proxy");
3961 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003962 }
3963 }
3964
3965 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3966 if (ret >= 0) {
3967 val = atoi(value);
3968 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3969 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08003970 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003971 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3972 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
3973 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3974 if (ret >= 0) {
3975 audio_extn_usb_remove_device(val, atoi(value));
3976 }
vivek mehta344576a2016-04-12 18:56:03 -07003977 ALOGV("detected USB disconnect .. enable proxy");
3978 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003979 }
3980 }
3981
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003982 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003983
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003984done:
3985 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003986 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303987error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003988 ALOGV("%s: exit with code(%d)", __func__, status);
3989 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990}
3991
3992static char* adev_get_parameters(const struct audio_hw_device *dev,
3993 const char *keys)
3994{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003995 struct audio_device *adev = (struct audio_device *)dev;
3996 struct str_parms *reply = str_parms_create();
3997 struct str_parms *query = str_parms_create_str(keys);
3998 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303999 char value[256] = {0};
4000 int ret = 0;
4001
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004002 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004003 if (reply) {
4004 str_parms_destroy(reply);
4005 }
4006 if (query) {
4007 str_parms_destroy(query);
4008 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004009 ALOGE("adev_get_parameters: failed to create query or reply");
4010 return NULL;
4011 }
4012
Naresh Tannirud7205b62014-06-20 02:54:48 +05304013 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4014 sizeof(value));
4015 if (ret >=0) {
4016 int val = 1;
4017 pthread_mutex_lock(&adev->snd_card_status.lock);
4018 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4019 val = 0;
4020 pthread_mutex_unlock(&adev->snd_card_status.lock);
4021 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4022 goto exit;
4023 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004024
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004025 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004026 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004027 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004028 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304029 pthread_mutex_unlock(&adev->lock);
4030
Naresh Tannirud7205b62014-06-20 02:54:48 +05304031exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004032 str = str_parms_to_str(reply);
4033 str_parms_destroy(query);
4034 str_parms_destroy(reply);
4035
4036 ALOGV("%s: exit: returns - %s", __func__, str);
4037 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038}
4039
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004040static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041{
4042 return 0;
4043}
4044
4045static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4046{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004047 int ret;
4048 struct audio_device *adev = (struct audio_device *)dev;
4049 pthread_mutex_lock(&adev->lock);
4050 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004051 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004052 pthread_mutex_unlock(&adev->lock);
4053 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054}
4055
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004056static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4057 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058{
4059 return -ENOSYS;
4060}
4061
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004062static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4063 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064{
4065 return -ENOSYS;
4066}
4067
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004068static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4069 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070{
4071 return -ENOSYS;
4072}
4073
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004074static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4075 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076{
4077 return -ENOSYS;
4078}
4079
4080static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4081{
4082 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 pthread_mutex_lock(&adev->lock);
4085 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004086 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004088 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004089 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004090 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004091 adev->current_call_output = NULL;
4092 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 }
4094 pthread_mutex_unlock(&adev->lock);
4095 return 0;
4096}
4097
4098static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4099{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004100 int ret;
4101
4102 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004103 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004104 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4105 pthread_mutex_unlock(&adev->lock);
4106
4107 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108}
4109
4110static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4111{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004112 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 return 0;
4114}
4115
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004116static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117 const struct audio_config *config)
4118{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004119 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004121 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4122 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123}
4124
4125static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004126 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004127 audio_devices_t devices,
4128 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004129 struct audio_stream_in **stream_in,
4130 audio_input_flags_t flags __unused,
4131 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004132 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133{
4134 struct audio_device *adev = (struct audio_device *)dev;
4135 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004136 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004137 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004138 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304141 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4142 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304144 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145
4146 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004147
4148 if (!in) {
4149 ALOGE("failed to allocate input stream");
4150 return -ENOMEM;
4151 }
4152
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304153 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304154 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4155 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004156 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004157 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159 in->stream.common.get_sample_rate = in_get_sample_rate;
4160 in->stream.common.set_sample_rate = in_set_sample_rate;
4161 in->stream.common.get_buffer_size = in_get_buffer_size;
4162 in->stream.common.get_channels = in_get_channels;
4163 in->stream.common.get_format = in_get_format;
4164 in->stream.common.set_format = in_set_format;
4165 in->stream.common.standby = in_standby;
4166 in->stream.common.dump = in_dump;
4167 in->stream.common.set_parameters = in_set_parameters;
4168 in->stream.common.get_parameters = in_get_parameters;
4169 in->stream.common.add_audio_effect = in_add_audio_effect;
4170 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4171 in->stream.set_gain = in_set_gain;
4172 in->stream.read = in_read;
4173 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4174
4175 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004176 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 in->standby = 1;
4179 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004180 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004181 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182
4183 /* Update config params with the requested sample rate and channels */
4184 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004185 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4186 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4187 is_low_latency = true;
4188#if LOW_LATENCY_CAPTURE_USE_CASE
4189 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4190#endif
4191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004194 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304195 in->bit_width = 16;
4196 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004198 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304199 if (adev->mode != AUDIO_MODE_IN_CALL) {
4200 ret = -EINVAL;
4201 goto err_open;
4202 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004203 if (config->sample_rate == 0)
4204 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4205 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4206 config->sample_rate != 8000) {
4207 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4208 ret = -EINVAL;
4209 goto err_open;
4210 }
4211 if (config->format == AUDIO_FORMAT_DEFAULT)
4212 config->format = AUDIO_FORMAT_PCM_16_BIT;
4213 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4214 config->format = AUDIO_FORMAT_PCM_16_BIT;
4215 ret = -EINVAL;
4216 goto err_open;
4217 }
4218
4219 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4220 in->config = pcm_config_afe_proxy_record;
4221 in->config.channels = channel_count;
4222 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304223 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304224 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4225 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004226 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004227 audio_extn_compr_cap_format_supported(config->format) &&
4228 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004229 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004230 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304231 /* restrict 24 bit capture for unprocessed source only
4232 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4233 */
4234 if (config->format == AUDIO_FORMAT_DEFAULT) {
4235 config->format = AUDIO_FORMAT_PCM_16_BIT;
4236 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4237 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4238 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4239 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4240 bool ret_error = false;
4241 in->bit_width = 24;
4242 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4243 from HAL is 24_packed and 8_24
4244 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4245 24_packed return error indicating supported format is 24_packed
4246 *> In case of any other source requesting 24 bit or float return error
4247 indicating format supported is 16 bit only.
4248
4249 on error flinger will retry with supported format passed
4250 */
4251 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4252 (source != AUDIO_SOURCE_CAMCORDER)) {
4253 config->format = AUDIO_FORMAT_PCM_16_BIT;
4254 if( config->sample_rate > 48000)
4255 config->sample_rate = 48000;
4256 ret_error = true;
4257 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4258 in->config.format = PCM_FORMAT_S24_3LE;
4259 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4260 in->config.format = PCM_FORMAT_S24_LE;
4261 } else {
4262 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4263 ret_error = true;
4264 }
4265
4266 if (ret_error) {
4267 ret = -EINVAL;
4268 goto err_open;
4269 }
4270 }
4271
4272 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004273 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004274 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004275 buffer_size = get_input_buffer_size(config->sample_rate,
4276 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004277 channel_count,
4278 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004279 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004280 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4281 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4282 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004283 (in->config.rate == 8000 || in->config.rate == 16000 ||
4284 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004285 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4286 voice_extn_compress_voip_open_input_stream(in);
4287 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004288 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004290 /* This stream could be for sound trigger lab,
4291 get sound trigger pcm if present */
4292 audio_extn_sound_trigger_check_and_get_session(in);
4293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004295 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004296 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004297
4298err_open:
4299 free(in);
4300 *stream_in = NULL;
4301 return ret;
4302}
4303
4304static void adev_close_input_stream(struct audio_hw_device *dev,
4305 struct audio_stream_in *stream)
4306{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004307 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004308 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004309 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304310
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304311 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004312
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304313 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004314 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304315
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004316 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304317 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004318 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304319 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004320 if (ret != 0)
4321 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4322 __func__, ret);
4323 } else
4324 in_standby(&stream->common);
4325
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004326 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004327 audio_extn_ssr_deinit();
4328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329
Mingming Yine62d7842013-10-25 16:26:03 -07004330 if(audio_extn_compr_cap_enabled() &&
4331 audio_extn_compr_cap_format_supported(in->config.format))
4332 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004333
Mingming Yinfd7607b2016-01-22 12:48:44 -08004334 if (in->is_st_session) {
4335 ALOGV("%s: sound trigger pcm stop lab", __func__);
4336 audio_extn_sound_trigger_stop_lab(in);
4337 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004338 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339 return;
4340}
4341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004342static int adev_dump(const audio_hw_device_t *device __unused,
4343 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344{
4345 return 0;
4346}
4347
4348static int adev_close(hw_device_t *device)
4349{
4350 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004351
4352 if (!adev)
4353 return 0;
4354
4355 pthread_mutex_lock(&adev_init_lock);
4356
4357 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004358 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004359 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004360 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004361 audio_route_free(adev->audio_route);
4362 free(adev->snd_dev_ref_cnt);
4363 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004364 if (adev->adm_deinit)
4365 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004366 free(device);
4367 adev = NULL;
4368 }
4369 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371 return 0;
4372}
4373
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004374/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4375 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4376 * just that it _might_ work.
4377 */
4378static int period_size_is_plausible_for_low_latency(int period_size)
4379{
4380 switch (period_size) {
4381 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004382 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004383 case 240:
4384 case 320:
4385 case 480:
4386 return 1;
4387 default:
4388 return 0;
4389 }
4390}
4391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392static int adev_open(const hw_module_t *module, const char *name,
4393 hw_device_t **device)
4394{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004395 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4397
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004398 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004399 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004400 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004401 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004402 ALOGD("%s: returning existing instance of adev", __func__);
4403 ALOGD("%s: exit", __func__);
4404 pthread_mutex_unlock(&adev_init_lock);
4405 return 0;
4406 }
4407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408 adev = calloc(1, sizeof(struct audio_device));
4409
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004410 if (!adev) {
4411 pthread_mutex_unlock(&adev_init_lock);
4412 return -ENOMEM;
4413 }
4414
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004415 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4418 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4419 adev->device.common.module = (struct hw_module_t *)module;
4420 adev->device.common.close = adev_close;
4421
4422 adev->device.init_check = adev_init_check;
4423 adev->device.set_voice_volume = adev_set_voice_volume;
4424 adev->device.set_master_volume = adev_set_master_volume;
4425 adev->device.get_master_volume = adev_get_master_volume;
4426 adev->device.set_master_mute = adev_set_master_mute;
4427 adev->device.get_master_mute = adev_get_master_mute;
4428 adev->device.set_mode = adev_set_mode;
4429 adev->device.set_mic_mute = adev_set_mic_mute;
4430 adev->device.get_mic_mute = adev_get_mic_mute;
4431 adev->device.set_parameters = adev_set_parameters;
4432 adev->device.get_parameters = adev_get_parameters;
4433 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4434 adev->device.open_output_stream = adev_open_output_stream;
4435 adev->device.close_output_stream = adev_close_output_stream;
4436 adev->device.open_input_stream = adev_open_input_stream;
4437 adev->device.close_input_stream = adev_close_input_stream;
4438 adev->device.dump = adev_dump;
4439
4440 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004442 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004443 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004446 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004447 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004448 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004449 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004450 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004451 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004452 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004453 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304454 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304455 adev->perf_lock_opts[0] = 0x101;
4456 adev->perf_lock_opts[1] = 0x20E;
4457 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304458
4459 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4460 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004462 adev->platform = platform_init(adev);
4463 if (!adev->platform) {
4464 free(adev->snd_dev_ref_cnt);
4465 free(adev);
4466 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4467 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004468 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004469 return -EINVAL;
4470 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004471
Naresh Tanniru4c630392014-05-12 01:05:52 +05304472 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4473
Eric Laurentc4aef752013-09-12 17:45:53 -07004474 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4475 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4476 if (adev->visualizer_lib == NULL) {
4477 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4478 } else {
4479 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4480 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004481 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004482 "visualizer_hal_start_output");
4483 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004484 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004485 "visualizer_hal_stop_output");
4486 }
4487 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004488 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004489 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004490
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004491 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4492 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4493 if (adev->offload_effects_lib == NULL) {
4494 ALOGE("%s: DLOPEN failed for %s", __func__,
4495 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4496 } else {
4497 ALOGV("%s: DLOPEN successful for %s", __func__,
4498 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4499 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304500 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004501 "offload_effects_bundle_hal_start_output");
4502 adev->offload_effects_stop_output =
4503 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4504 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004505 adev->offload_effects_set_hpx_state =
4506 (int (*)(bool))dlsym(adev->offload_effects_lib,
4507 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304508 adev->offload_effects_get_parameters =
4509 (void (*)(struct str_parms *, struct str_parms *))
4510 dlsym(adev->offload_effects_lib,
4511 "offload_effects_bundle_get_parameters");
4512 adev->offload_effects_set_parameters =
4513 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4514 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004515 }
4516 }
4517
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004518 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4519 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4520 if (adev->adm_lib == NULL) {
4521 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4522 } else {
4523 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4524 adev->adm_init = (adm_init_t)
4525 dlsym(adev->adm_lib, "adm_init");
4526 adev->adm_deinit = (adm_deinit_t)
4527 dlsym(adev->adm_lib, "adm_deinit");
4528 adev->adm_register_input_stream = (adm_register_input_stream_t)
4529 dlsym(adev->adm_lib, "adm_register_input_stream");
4530 adev->adm_register_output_stream = (adm_register_output_stream_t)
4531 dlsym(adev->adm_lib, "adm_register_output_stream");
4532 adev->adm_deregister_stream = (adm_deregister_stream_t)
4533 dlsym(adev->adm_lib, "adm_deregister_stream");
4534 adev->adm_request_focus = (adm_request_focus_t)
4535 dlsym(adev->adm_lib, "adm_request_focus");
4536 adev->adm_abandon_focus = (adm_abandon_focus_t)
4537 dlsym(adev->adm_lib, "adm_abandon_focus");
4538 }
4539 }
4540
Mingming Yin514a8bc2014-07-29 15:22:21 -07004541 adev->bt_wb_speech_enabled = false;
4542
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004543 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 *device = &adev->device.common;
4545
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004546 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4547 &adev->streams_output_cfg_list);
4548
Kiran Kandi910e1862013-10-29 13:29:42 -07004549 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004550
4551 char value[PROPERTY_VALUE_MAX];
4552 int trial;
4553 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4554 trial = atoi(value);
4555 if (period_size_is_plausible_for_low_latency(trial)) {
4556 pcm_config_low_latency.period_size = trial;
4557 pcm_config_low_latency.start_threshold = trial / 4;
4558 pcm_config_low_latency.avail_min = trial / 4;
4559 configured_low_latency_capture_period_size = trial;
4560 }
4561 }
4562 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4563 trial = atoi(value);
4564 if (period_size_is_plausible_for_low_latency(trial)) {
4565 configured_low_latency_capture_period_size = trial;
4566 }
4567 }
4568
vivek mehta446c3962015-09-14 10:57:35 -07004569 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004570 pthread_mutex_unlock(&adev_init_lock);
4571
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004572 if (adev->adm_init)
4573 adev->adm_data = adev->adm_init();
4574
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304575 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004576 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 return 0;
4578}
4579
4580static struct hw_module_methods_t hal_module_methods = {
4581 .open = adev_open,
4582};
4583
4584struct audio_module HAL_MODULE_INFO_SYM = {
4585 .common = {
4586 .tag = HARDWARE_MODULE_TAG,
4587 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4588 .hal_api_version = HARDWARE_HAL_API_VERSION,
4589 .id = AUDIO_HARDWARE_MODULE_ID,
4590 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004591 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592 .methods = &hal_module_methods,
4593 },
4594};