blob: 95595b4eb789f0e5f81c055fecd5567c6fb9116b [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053067#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080068#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070069#include "platform_api.h"
70#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070071#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080072#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080073
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080075#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053078/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
79#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080081#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
83
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070084#define PROXY_OPEN_RETRY_COUNT 100
85#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080086
Mingming Yin08c7e312015-03-16 18:10:58 -070087#ifdef USE_LL_AS_PRIMARY_OUTPUT
88#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
89#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
90#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070092#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
93#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070095static unsigned int configured_low_latency_capture_period_size =
96 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
97
Eric Laurentb23d5282013-05-14 15:27:20 -070098struct pcm_config pcm_config_deep_buffer = {
99 .channels = 2,
100 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
101 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
102 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
103 .format = PCM_FORMAT_S16_LE,
104 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
105 .stop_threshold = INT_MAX,
106 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
107};
108
109struct pcm_config pcm_config_low_latency = {
110 .channels = 2,
111 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
112 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
113 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
114 .format = PCM_FORMAT_S16_LE,
115 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
116 .stop_threshold = INT_MAX,
117 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
118};
119
120struct pcm_config pcm_config_hdmi_multi = {
121 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
122 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
123 .period_size = HDMI_MULTI_PERIOD_SIZE,
124 .period_count = HDMI_MULTI_PERIOD_COUNT,
125 .format = PCM_FORMAT_S16_LE,
126 .start_threshold = 0,
127 .stop_threshold = INT_MAX,
128 .avail_min = 0,
129};
130
131struct pcm_config pcm_config_audio_capture = {
132 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700133 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
134 .format = PCM_FORMAT_S16_LE,
135};
136
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700137#define AFE_PROXY_CHANNEL_COUNT 2
138#define AFE_PROXY_SAMPLING_RATE 48000
139
140#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
141#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
142
143struct pcm_config pcm_config_afe_proxy_playback = {
144 .channels = AFE_PROXY_CHANNEL_COUNT,
145 .rate = AFE_PROXY_SAMPLING_RATE,
146 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
150 .stop_threshold = INT_MAX,
151 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
152};
153
154#define AFE_PROXY_RECORD_PERIOD_SIZE 768
155#define AFE_PROXY_RECORD_PERIOD_COUNT 4
156
157struct pcm_config pcm_config_afe_proxy_record = {
158 .channels = AFE_PROXY_CHANNEL_COUNT,
159 .rate = AFE_PROXY_SAMPLING_RATE,
160 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
164 .stop_threshold = INT_MAX,
165 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
166};
167
Ashish Jainf1eaa582016-05-23 20:54:24 +0530168#define AUDIO_MAX_PCM_FORMATS 7
169
170const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
171 [AUDIO_FORMAT_DEFAULT] = 0,
172 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
173 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
174 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
175 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
176 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
177 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
178};
179
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800180const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
182 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700183 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
184 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700185 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700186 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700187 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
188 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
189 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
190 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
191 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
192 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
193 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
194 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700195
Eric Laurentb23d5282013-05-14 15:27:20 -0700196 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700197 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700198 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700199 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700200 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800201 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800202 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700203 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700204
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700205 [USECASE_VOICE2_CALL] = "voice2-call",
206 [USECASE_VOLTE_CALL] = "volte-call",
207 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800208 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800209 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
210 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800211 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700212 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
213 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
214 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800215 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
216 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
217 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
218
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700219 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
220 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700221 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
222 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700223
224 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
225 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700226};
227
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700228static const audio_usecase_t offload_usecases[] = {
229 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700230 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
231 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
232 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
233 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
234 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
235 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
236 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
237 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700238};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239
240#define STRING_TO_ENUM(string) { #string, string }
241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800242struct string_to_enum {
243 const char *name;
244 uint32_t value;
245};
246
247static const struct string_to_enum out_channels_name_to_enum_table[] = {
248 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800249 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
250 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
251 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700252 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800253 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
254 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800255 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
256};
257
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700258static const struct string_to_enum out_formats_name_to_enum_table[] = {
259 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
260 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
261 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800262 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
263 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
264};
265
266//list of all supported sample rates by HDMI specification.
267static const int out_hdmi_sample_rates[] = {
268 32000, 44100, 48000, 88200, 96000, 176400, 192000,
269};
270
271static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
272 STRING_TO_ENUM(32000),
273 STRING_TO_ENUM(44100),
274 STRING_TO_ENUM(48000),
275 STRING_TO_ENUM(88200),
276 STRING_TO_ENUM(96000),
277 STRING_TO_ENUM(176400),
278 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700279};
280
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700281static struct audio_device *adev = NULL;
282static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700283static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700284//cache last MBDRC cal step level
285static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700286
vivek mehtaa76401a2015-04-24 14:12:15 -0700287__attribute__ ((visibility ("default")))
288bool audio_hw_send_gain_dep_calibration(int level) {
289 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700290 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700291
292 pthread_mutex_lock(&adev_init_lock);
293
294 if (adev != NULL && adev->platform != NULL) {
295 pthread_mutex_lock(&adev->lock);
296 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700297
298 // if cal set fails, cache level info
299 // if cal set succeds, reset known last cal set
300 if (!ret_val)
301 last_known_cal_step = level;
302 else if (last_known_cal_step != -1)
303 last_known_cal_step = -1;
304
vivek mehtaa76401a2015-04-24 14:12:15 -0700305 pthread_mutex_unlock(&adev->lock);
306 } else {
307 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
308 }
309
310 pthread_mutex_unlock(&adev_init_lock);
311
312 return ret_val;
313}
314
Ashish Jain5106d362016-05-11 19:23:33 +0530315static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
316{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800317 bool gapless_enabled = false;
318 const char *mixer_ctl_name = "Compress Gapless Playback";
319 struct mixer_ctl *ctl;
320
321 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530322 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
323
324 /*Disable gapless if its AV playback*/
325 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800326
327 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
328 if (!ctl) {
329 ALOGE("%s: Could not get ctl for mixer cmd - %s",
330 __func__, mixer_ctl_name);
331 return -EINVAL;
332 }
333
334 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
335 ALOGE("%s: Could not set gapless mode %d",
336 __func__, gapless_enabled);
337 return -EINVAL;
338 }
339 return 0;
340}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700341
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700342static bool is_supported_format(audio_format_t format)
343{
Eric Laurent86e17132013-09-12 17:49:30 -0700344 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530345 format == AUDIO_FORMAT_AAC_LC ||
346 format == AUDIO_FORMAT_AAC_HE_V1 ||
347 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530348 format == AUDIO_FORMAT_AAC_ADTS_LC ||
349 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
350 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530351 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
352 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530353 format == AUDIO_FORMAT_PCM_FLOAT ||
354 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700355 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530356 format == AUDIO_FORMAT_AC3 ||
357 format == AUDIO_FORMAT_E_AC3 ||
358 format == AUDIO_FORMAT_DTS ||
359 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800360 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530361 format == AUDIO_FORMAT_ALAC ||
362 format == AUDIO_FORMAT_APE ||
363 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800364 format == AUDIO_FORMAT_WMA ||
365 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800366 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700367
368 return false;
369}
370
371static int get_snd_codec_id(audio_format_t format)
372{
373 int id = 0;
374
Ashish Jainf9b78162014-08-25 20:36:25 +0530375 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700376 case AUDIO_FORMAT_MP3:
377 id = SND_AUDIOCODEC_MP3;
378 break;
379 case AUDIO_FORMAT_AAC:
380 id = SND_AUDIOCODEC_AAC;
381 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530382 case AUDIO_FORMAT_AAC_ADTS:
383 id = SND_AUDIOCODEC_AAC;
384 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700385 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800386 id = SND_AUDIOCODEC_PCM;
387 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700388 case AUDIO_FORMAT_FLAC:
389 id = SND_AUDIOCODEC_FLAC;
390 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530391 case AUDIO_FORMAT_ALAC:
392 id = SND_AUDIOCODEC_ALAC;
393 break;
394 case AUDIO_FORMAT_APE:
395 id = SND_AUDIOCODEC_APE;
396 break;
397 case AUDIO_FORMAT_VORBIS:
398 id = SND_AUDIOCODEC_VORBIS;
399 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800400 case AUDIO_FORMAT_WMA:
401 id = SND_AUDIOCODEC_WMA;
402 break;
403 case AUDIO_FORMAT_WMA_PRO:
404 id = SND_AUDIOCODEC_WMA_PRO;
405 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530406 case AUDIO_FORMAT_AC3:
407 id = SND_AUDIOCODEC_AC3;
408 break;
409 case AUDIO_FORMAT_E_AC3:
410 case AUDIO_FORMAT_E_AC3_JOC:
411 id = SND_AUDIOCODEC_EAC3;
412 break;
413 case AUDIO_FORMAT_DTS:
414 case AUDIO_FORMAT_DTS_HD:
415 id = SND_AUDIOCODEC_DTS;
416 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700417 default:
Mingming Yin90310102013-11-13 16:57:00 -0800418 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700419 }
420
421 return id;
422}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800423
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530424int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530425{
426 int snd_scard_state;
427
428 if (!adev)
429 return SND_CARD_STATE_OFFLINE;
430
431 pthread_mutex_lock(&adev->snd_card_status.lock);
432 snd_scard_state = adev->snd_card_status.state;
433 pthread_mutex_unlock(&adev->snd_card_status.lock);
434
435 return snd_scard_state;
436}
437
438static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
439{
440 if (!adev)
441 return -ENOSYS;
442
443 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700444 if (adev->snd_card_status.state != snd_scard_state) {
445 adev->snd_card_status.state = snd_scard_state;
446 platform_snd_card_update(adev->platform, snd_scard_state);
447 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530448 pthread_mutex_unlock(&adev->snd_card_status.lock);
449
450 return 0;
451}
452
Avinash Vaish71a8b972014-07-24 15:36:33 +0530453static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
454 struct audio_usecase *uc_info)
455{
456 struct listnode *node;
457 struct audio_usecase *usecase;
458
459 if (uc_info == NULL)
460 return -EINVAL;
461
462 /* Re-route all voice usecases on the shared backend other than the
463 specified usecase to new snd devices */
464 list_for_each(node, &adev->usecase_list) {
465 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800466 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530467 enable_audio_route(adev, usecase);
468 }
469 return 0;
470}
471
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700472int pcm_ioctl(struct pcm *pcm, int request, ...)
473{
474 va_list ap;
475 void * arg;
476 int pcm_fd = *(int*)pcm;
477
478 va_start(ap, request);
479 arg = va_arg(ap, void *);
480 va_end(ap);
481
482 return ioctl(pcm_fd, request, arg);
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700488 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700489 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800490
491 if (usecase == NULL)
492 return -EINVAL;
493
494 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
495
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800496 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700497 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800498 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700499 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800500
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800501#ifdef DS1_DOLBY_DAP_ENABLED
502 audio_extn_dolby_set_dmid(adev);
503 audio_extn_dolby_set_endpoint(adev);
504#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700505 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700506 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530507 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700508 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530509 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800510 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700511 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700512 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700513 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800514 ALOGV("%s: exit", __func__);
515 return 0;
516}
517
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700518int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700519 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700522 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800523
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530524 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800525 return -EINVAL;
526
527 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700528 if (usecase->type == PCM_CAPTURE)
529 snd_device = usecase->in_snd_device;
530 else
531 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800532 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700533 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700534 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700535 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530537 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800538 ALOGV("%s: exit", __func__);
539 return 0;
540}
541
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700542int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700543 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530545 int i, num_devices = 0;
546 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700547 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
548
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800549 if (snd_device < SND_DEVICE_MIN ||
550 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800551 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800552 return -EINVAL;
553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554
555 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700556
557 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
558 ALOGE("%s: Invalid sound device returned", __func__);
559 return -EINVAL;
560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700562 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700563 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 return 0;
565 }
566
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530567
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700568 if (audio_extn_spkr_prot_is_enabled())
569 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700570
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700571
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800572 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
573 audio_extn_spkr_prot_is_enabled()) {
574 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700575 adev->snd_dev_ref_cnt[snd_device]--;
576 return -EINVAL;
577 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200578 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800579 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800580 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200581 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800582 return -EINVAL;
583 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530584 } else if (platform_can_split_snd_device(adev->platform, snd_device,
585 &num_devices, new_snd_devices)) {
586 for (i = 0; i < num_devices; i++) {
587 enable_snd_device(adev, new_snd_devices[i]);
588 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800589 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700590 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700591 /* due to the possibility of calibration overwrite between listen
592 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700593 audio_extn_sound_trigger_update_device_status(snd_device,
594 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530595 audio_extn_listen_update_device_status(snd_device,
596 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700597 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700598 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700599 audio_extn_sound_trigger_update_device_status(snd_device,
600 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530601 audio_extn_listen_update_device_status(snd_device,
602 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700603 return -EINVAL;
604 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300605 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700606 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530607
608 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
609 !adev->native_playback_enabled &&
610 audio_is_true_native_stream_active(adev)) {
611 ALOGD("%s: %d: napb: enabling native mode in hardware",
612 __func__, __LINE__);
613 audio_route_apply_and_update_path(adev->audio_route,
614 "true-native-mode");
615 adev->native_playback_enabled = true;
616 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800618 return 0;
619}
620
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700621int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700622 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530624 int i, num_devices = 0;
625 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700626 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
627
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800628 if (snd_device < SND_DEVICE_MIN ||
629 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800630 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 return -EINVAL;
632 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
634 ALOGE("%s: device ref cnt is already 0", __func__);
635 return -EINVAL;
636 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700637
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700639
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700640 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
641 ALOGE("%s: Invalid sound device returned", __func__);
642 return -EINVAL;
643 }
644
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700646 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800647 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
648 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700649 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530650 } else if (platform_can_split_snd_device(adev->platform, snd_device,
651 &num_devices, new_snd_devices)) {
652 for (i = 0; i < num_devices; i++) {
653 disable_snd_device(adev, new_snd_devices[i]);
654 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300655 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700656 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300657 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700658
Ashish Jain81eb2a82015-05-13 10:52:34 +0530659 if (snd_device == SND_DEVICE_OUT_HDMI)
660 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530661 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
662 adev->native_playback_enabled) {
663 ALOGD("%s: %d: napb: disabling native mode in hardware",
664 __func__, __LINE__);
665 audio_route_reset_and_update_path(adev->audio_route,
666 "true-native-mode");
667 adev->native_playback_enabled = false;
668 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530669
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200670 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700671 audio_extn_sound_trigger_update_device_status(snd_device,
672 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530673 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800674 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677 return 0;
678}
679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530681 struct audio_usecase *uc_info,
682 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683{
684 struct listnode *node;
685 struct audio_usecase *usecase;
686 bool switch_device[AUDIO_USECASE_MAX];
687 int i, num_uc_to_switch = 0;
688
689 /*
690 * This function is to make sure that all the usecases that are active on
691 * the hardware codec backend are always routed to any one device that is
692 * handled by the hardware codec.
693 * For example, if low-latency and deep-buffer usecases are currently active
694 * on speaker and out_set_parameters(headset) is received on low-latency
695 * output, then we have to make sure deep-buffer is also switched to headset,
696 * because of the limitation that both the devices cannot be enabled
697 * at the same time as they share the same backend.
698 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700699 /*
700 * This call is to check if we need to force routing for a particular stream
701 * If there is a backend configuration change for the device when a
702 * new stream starts, then ADM needs to be closed and re-opened with the new
703 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800704 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700705 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800706 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
707 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530708
709 ALOGD("%s:becf: force routing %d", __func__, force_routing);
710
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800712 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800713 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700714 for (i = 0; i < AUDIO_USECASE_MAX; i++)
715 switch_device[i] = false;
716
717 list_for_each(node, &adev->usecase_list) {
718 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800719
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530720 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
721 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530722 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530723 platform_get_snd_device_name(usecase->out_snd_device),
724 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800725 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530726 usecase != uc_info &&
727 (usecase->out_snd_device != snd_device || force_routing) &&
728 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
729 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
730 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
731 __func__, use_case_table[usecase->id],
732 platform_get_snd_device_name(usecase->out_snd_device));
733 disable_audio_route(adev, usecase);
734 switch_device[usecase->id] = true;
735 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 }
737 }
738
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530739 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
740 num_uc_to_switch);
741
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530745 /* Make sure the previous devices to be disabled first and then enable the
746 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 list_for_each(node, &adev->usecase_list) {
748 usecase = node_to_item(node, struct audio_usecase, list);
749 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700750 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 }
752 }
753
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700754 list_for_each(node, &adev->usecase_list) {
755 usecase = node_to_item(node, struct audio_usecase, list);
756 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700757 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700758 }
759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 /* Re-route all the usecases on the shared backend other than the
762 specified usecase to new snd devices */
763 list_for_each(node, &adev->usecase_list) {
764 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530765 /* Update the out_snd_device only before enabling the audio route */
766 if (switch_device[usecase->id]) {
767 usecase->out_snd_device = snd_device;
768 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530769 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530770 use_case_table[usecase->id],
771 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530772 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530773 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700774 }
775 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700776 }
777}
778
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530779static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700780 struct audio_usecase *uc_info,
781 snd_device_t snd_device)
782{
783 struct listnode *node;
784 struct audio_usecase *usecase;
785 bool switch_device[AUDIO_USECASE_MAX];
786 int i, num_uc_to_switch = 0;
787
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530788 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
789 snd_device);
790 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700791 /*
792 * This function is to make sure that all the active capture usecases
793 * are always routed to the same input sound device.
794 * For example, if audio-record and voice-call usecases are currently
795 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
796 * is received for voice call then we have to make sure that audio-record
797 * usecase is also switched to earpiece i.e. voice-dmic-ef,
798 * because of the limitation that two devices cannot be enabled
799 * at the same time if they share the same backend.
800 */
801 for (i = 0; i < AUDIO_USECASE_MAX; i++)
802 switch_device[i] = false;
803
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800806 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530808 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700809 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530810 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
811 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700812 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700813 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
814 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700815 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700816 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700817 switch_device[usecase->id] = true;
818 num_uc_to_switch++;
819 }
820 }
821
822 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700823 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700824
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530825 /* Make sure the previous devices to be disabled first and then enable the
826 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700827 list_for_each(node, &adev->usecase_list) {
828 usecase = node_to_item(node, struct audio_usecase, list);
829 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700830 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800831 }
832 }
833
834 list_for_each(node, &adev->usecase_list) {
835 usecase = node_to_item(node, struct audio_usecase, list);
836 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700837 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700838 }
839 }
840
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700841 /* Re-route all the usecases on the shared backend other than the
842 specified usecase to new snd devices */
843 list_for_each(node, &adev->usecase_list) {
844 usecase = node_to_item(node, struct audio_usecase, list);
845 /* Update the in_snd_device only before enabling the audio route */
846 if (switch_device[usecase->id] ) {
847 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800848 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530849 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700850 }
851 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700852 }
853}
854
Mingming Yin3a941d42016-02-17 18:08:05 -0800855static void reset_hdmi_sink_caps(struct stream_out *out) {
856 int i = 0;
857
858 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
859 out->supported_channel_masks[i] = 0;
860 }
861 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
862 out->supported_formats[i] = 0;
863 }
864 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
865 out->supported_sample_rates[i] = 0;
866 }
867}
868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800869/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800870static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871{
Mingming Yin3a941d42016-02-17 18:08:05 -0800872 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700873 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874
Mingming Yin3a941d42016-02-17 18:08:05 -0800875 reset_hdmi_sink_caps(out);
876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800879 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700880 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800881 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
882 case 6:
883 ALOGV("%s: HDMI supports 5.1 channels", __func__);
884 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
885 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
886 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
887 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
888 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800889 break;
890 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800891 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700892 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800893 break;
894 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800895
896 // check channel format caps
897 i = 0;
898 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
899 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
900 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
901 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
902 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
903 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
904 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
905 }
906
907 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
908 ALOGV(":%s HDMI supports DTS format", __func__);
909 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
910 }
911
912 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
913 ALOGV(":%s HDMI supports DTS HD format", __func__);
914 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
915 }
916
917
918 // check sample rate caps
919 i = 0;
920 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
921 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
922 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
923 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
924 }
925 }
926
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700927 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928}
929
Alexy Josephb1379942016-01-29 15:49:38 -0800930audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800931 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700932{
933 struct audio_usecase *usecase;
934 struct listnode *node;
935
936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800938 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700939 ALOGV("%s: usecase id %d", __func__, usecase->id);
940 return usecase->id;
941 }
942 }
943 return USECASE_INVALID;
944}
945
Alexy Josephb1379942016-01-29 15:49:38 -0800946struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700947 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948{
949 struct audio_usecase *usecase;
950 struct listnode *node;
951
952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (usecase->id == uc_id)
955 return usecase;
956 }
957 return NULL;
958}
959
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530960/*
961 * is a true native playback active
962 */
963bool audio_is_true_native_stream_active(struct audio_device *adev)
964{
965 bool active = false;
966 int i = 0;
967 struct listnode *node;
968
969 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
970 ALOGV("%s:napb: not in true mode or non hdphones device",
971 __func__);
972 active = false;
973 goto exit;
974 }
975
976 list_for_each(node, &adev->usecase_list) {
977 struct audio_usecase *uc;
978 uc = node_to_item(node, struct audio_usecase, list);
979 struct stream_out *curr_out =
980 (struct stream_out*) uc->stream.out;
981
982 if (curr_out && PCM_PLAYBACK == uc->type) {
983 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
984 "(%d) device %s", __func__, i++, use_case_table[uc->id],
985 uc->id, curr_out->sample_rate,
986 curr_out->bit_width,
987 platform_get_snd_device_name(uc->out_snd_device));
988
989 if (is_offload_usecase(uc->id) &&
990 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
991 active = true;
992 ALOGD("%s:napb:native stream detected", __func__);
993 }
994 }
995 }
996exit:
997 return active;
998}
999
1000
1001static bool force_device_switch(struct audio_usecase *usecase)
1002{
1003 bool ret = false;
1004 bool is_it_true_mode = false;
1005
1006 if (is_offload_usecase(usecase->id) &&
1007 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001008 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1009 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1010 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301011 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1012 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1013 (!is_it_true_mode && adev->native_playback_enabled)){
1014 ret = true;
1015 ALOGD("napb: time to toggle native mode");
1016 }
1017 }
1018
1019 return ret;
1020}
1021
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001022int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001024 snd_device_t out_snd_device = SND_DEVICE_NONE;
1025 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001026 struct audio_usecase *usecase = NULL;
1027 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001028 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001029 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001030 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301033 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1034
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035 usecase = get_usecase_from_list(adev, uc_id);
1036 if (usecase == NULL) {
1037 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1038 return -EINVAL;
1039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001041 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001042 (usecase->type == VOIP_CALL) ||
1043 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001044 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001045 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001046 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047 usecase->devices = usecase->stream.out->devices;
1048 } else {
1049 /*
1050 * If the voice call is active, use the sound devices of voice call usecase
1051 * so that it would not result any device switch. All the usecases will
1052 * be switched to new device when select_devices() is called for voice call
1053 * usecase. This is to avoid switching devices for voice call when
1054 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001055 * choose voice call device only if the use case device is
1056 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001058 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001059 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001060 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001061 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1062 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1063 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001064 in_snd_device = vc_usecase->in_snd_device;
1065 out_snd_device = vc_usecase->out_snd_device;
1066 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001067 } else if (voice_extn_compress_voip_is_active(adev)) {
1068 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001069 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301070 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001071 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001072 in_snd_device = voip_usecase->in_snd_device;
1073 out_snd_device = voip_usecase->out_snd_device;
1074 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001075 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001076 hfp_ucid = audio_extn_hfp_get_usecase();
1077 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001078 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001079 in_snd_device = hfp_usecase->in_snd_device;
1080 out_snd_device = hfp_usecase->out_snd_device;
1081 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 }
1083 if (usecase->type == PCM_PLAYBACK) {
1084 usecase->devices = usecase->stream.out->devices;
1085 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001086 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001087 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001088 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001089 if (usecase->stream.out == adev->primary_output &&
1090 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001091 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001092 select_devices(adev, adev->active_input->usecase);
1093 }
1094 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 } else if (usecase->type == PCM_CAPTURE) {
1096 usecase->devices = usecase->stream.in->device;
1097 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001098 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001099 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001100 if (adev->active_input &&
1101 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301102 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1103 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1104 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001105 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001106 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001107 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1108 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001109 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001110 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001111 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 }
1113 }
1114
1115 if (out_snd_device == usecase->out_snd_device &&
1116 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301117
1118 if (!force_device_switch(usecase))
1119 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 }
1121
sangwoobc677242013-08-08 16:53:43 +09001122 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001123 out_snd_device, platform_get_snd_device_name(out_snd_device),
1124 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 /*
1127 * Limitation: While in call, to do a device switch we need to disable
1128 * and enable both RX and TX devices though one of them is same as current
1129 * device.
1130 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001131 if ((usecase->type == VOICE_CALL) &&
1132 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1133 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001134 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001135 }
1136
1137 if (((usecase->type == VOICE_CALL) ||
1138 (usecase->type == VOIP_CALL)) &&
1139 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1140 /* Disable sidetone only if voice/voip call already exists */
1141 if (voice_is_call_state_active(adev) ||
1142 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001143 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001144 }
1145
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 /* Disable current sound devices */
1147 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001148 disable_audio_route(adev, usecase);
1149 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 }
1151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001153 disable_audio_route(adev, usecase);
1154 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 }
1156
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001157 /* Applicable only on the targets that has external modem.
1158 * New device information should be sent to modem before enabling
1159 * the devices to reduce in-call device switch time.
1160 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001161 if ((usecase->type == VOICE_CALL) &&
1162 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1163 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001164 status = platform_switch_voice_call_enable_device_config(adev->platform,
1165 out_snd_device,
1166 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001167 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001168
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 /* Enable new sound devices */
1170 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001171 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001172 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 }
1174
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301176 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001177 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179
Avinash Vaish71a8b972014-07-24 15:36:33 +05301180 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001181 status = platform_switch_voice_call_device_post(adev->platform,
1182 out_snd_device,
1183 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301184 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001185 /* Enable sidetone only if voice/voip call already exists */
1186 if (voice_is_call_state_active(adev) ||
1187 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001188 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301189 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001190
sangwoo170731f2013-06-08 15:36:36 +09001191 usecase->in_snd_device = in_snd_device;
1192 usecase->out_snd_device = out_snd_device;
1193
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301194 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001195 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301196 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001197 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301198 usecase->stream.out->flags,
1199 usecase->stream.out->format,
1200 usecase->stream.out->sample_rate,
1201 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301202 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301203 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001204 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301205 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001206
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001207 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001208
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001209 /* Applicable only on the targets that has external modem.
1210 * Enable device command should be sent to modem only after
1211 * enabling voice call mixer controls
1212 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001213 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001214 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1215 out_snd_device,
1216 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301217 ALOGD("%s: done",__func__);
1218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219 return status;
1220}
1221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222static int stop_input_stream(struct stream_in *in)
1223{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301224 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 struct audio_usecase *uc_info;
1226 struct audio_device *adev = in->dev;
1227
Eric Laurentc8400632013-02-14 19:04:54 -08001228 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229
Eric Laurent994a6932013-07-17 11:51:42 -07001230 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 uc_info = get_usecase_from_list(adev, in->usecase);
1233 if (uc_info == NULL) {
1234 ALOGE("%s: Could not find the usecase (%d) in the list",
1235 __func__, in->usecase);
1236 return -EINVAL;
1237 }
1238
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001239 /* Close in-call recording streams */
1240 voice_check_and_stop_incall_rec_usecase(adev, in);
1241
Eric Laurent150dbfe2013-02-27 14:31:02 -08001242 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001243 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244
1245 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001246 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001248 list_remove(&uc_info->list);
1249 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250
Eric Laurent994a6932013-07-17 11:51:42 -07001251 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 return ret;
1253}
1254
1255int start_input_stream(struct stream_in *in)
1256{
1257 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001258 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 struct audio_usecase *uc_info;
1260 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301261 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262
Mingming Yin2664a5b2015-09-03 10:53:11 -07001263 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1264 if (get_usecase_from_list(adev, usecase) == NULL)
1265 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301266 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1267 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001268
Naresh Tanniru80659832014-06-04 18:17:56 +05301269
1270 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301271 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301272 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301273 goto error_config;
1274 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301275
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001276 /* Check if source matches incall recording usecase criteria */
1277 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1278 if (ret)
1279 goto error_config;
1280 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001281 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1282
1283 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1284 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1285 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001286 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001287 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001288
Eric Laurentb23d5282013-05-14 15:27:20 -07001289 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 if (in->pcm_device_id < 0) {
1291 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1292 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001293 ret = -EINVAL;
1294 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296
1297 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001299
1300 if (!uc_info) {
1301 ret = -ENOMEM;
1302 goto error_config;
1303 }
1304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305 uc_info->id = in->usecase;
1306 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001307 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 uc_info->devices = in->device;
1309 uc_info->in_snd_device = SND_DEVICE_NONE;
1310 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001312 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301313 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1314 adev->perf_lock_opts,
1315 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301318 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1319 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001320
1321 unsigned int flags = PCM_IN;
1322 unsigned int pcm_open_retry_count = 0;
1323
1324 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1325 flags |= PCM_MMAP | PCM_NOIRQ;
1326 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1327 }
1328
1329 while (1) {
1330 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1331 flags, &in->config);
1332 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1333 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1334 if (in->pcm != NULL) {
1335 pcm_close(in->pcm);
1336 in->pcm = NULL;
1337 }
1338 if (pcm_open_retry_count-- == 0) {
1339 ret = -EIO;
1340 goto error_open;
1341 }
1342 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1343 continue;
1344 }
1345 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001347
1348 ALOGV("%s: pcm_prepare", __func__);
1349 ret = pcm_prepare(in->pcm);
1350 if (ret < 0) {
1351 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1352 pcm_close(in->pcm);
1353 in->pcm = NULL;
1354 goto error_open;
1355 }
1356
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301357 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001358 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001359
Eric Laurentc8400632013-02-14 19:04:54 -08001360 return ret;
1361
1362error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301363 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001365error_config:
1366 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301367 /*
1368 * sleep 50ms to allow sufficient time for kernel
1369 * drivers to recover incases like SSR.
1370 */
1371 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001373
1374 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375}
1376
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001377void lock_input_stream(struct stream_in *in)
1378{
1379 pthread_mutex_lock(&in->pre_lock);
1380 pthread_mutex_lock(&in->lock);
1381 pthread_mutex_unlock(&in->pre_lock);
1382}
1383
1384void lock_output_stream(struct stream_out *out)
1385{
1386 pthread_mutex_lock(&out->pre_lock);
1387 pthread_mutex_lock(&out->lock);
1388 pthread_mutex_unlock(&out->pre_lock);
1389}
1390
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001391/* must be called with out->lock locked */
1392static int send_offload_cmd_l(struct stream_out* out, int command)
1393{
1394 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1395
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001396 if (!cmd) {
1397 ALOGE("failed to allocate mem for command 0x%x", command);
1398 return -ENOMEM;
1399 }
1400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001401 ALOGVV("%s %d", __func__, command);
1402
1403 cmd->cmd = command;
1404 list_add_tail(&out->offload_cmd_list, &cmd->node);
1405 pthread_cond_signal(&out->offload_cond);
1406 return 0;
1407}
1408
1409/* must be called iwth out->lock locked */
1410static void stop_compressed_output_l(struct stream_out *out)
1411{
1412 out->offload_state = OFFLOAD_STATE_IDLE;
1413 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001414 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001415 if (out->compr != NULL) {
1416 compress_stop(out->compr);
1417 while (out->offload_thread_blocked) {
1418 pthread_cond_wait(&out->cond, &out->lock);
1419 }
1420 }
1421}
1422
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001423bool is_offload_usecase(audio_usecase_t uc_id)
1424{
1425 unsigned int i;
1426 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1427 if (uc_id == offload_usecases[i])
1428 return true;
1429 }
1430 return false;
1431}
1432
vivek mehta446c3962015-09-14 10:57:35 -07001433static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001434{
vivek mehta446c3962015-09-14 10:57:35 -07001435 audio_usecase_t ret_uc = USECASE_INVALID;
1436 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001437 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001438 if (!adev->multi_offload_enable) {
1439 if (is_direct_pcm)
1440 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1441 else
1442 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001443
vivek mehta446c3962015-09-14 10:57:35 -07001444 pthread_mutex_lock(&adev->lock);
1445 if (get_usecase_from_list(adev, ret_uc) != NULL)
1446 ret_uc = USECASE_INVALID;
1447 pthread_mutex_unlock(&adev->lock);
1448
1449 return ret_uc;
1450 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001451
1452 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001453 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1454 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1455 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1456 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001457 break;
1458 }
1459 }
vivek mehta446c3962015-09-14 10:57:35 -07001460
1461 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1462 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001463}
1464
1465static void free_offload_usecase(struct audio_device *adev,
1466 audio_usecase_t uc_id)
1467{
vivek mehta446c3962015-09-14 10:57:35 -07001468 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001469 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001470
1471 if (!adev->multi_offload_enable)
1472 return;
1473
1474 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1475 if (offload_usecases[offload_uc_index] == uc_id) {
1476 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001477 break;
1478 }
1479 }
1480 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1481}
1482
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483static void *offload_thread_loop(void *context)
1484{
1485 struct stream_out *out = (struct stream_out *) context;
1486 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001487 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001488
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001489 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1490 set_sched_policy(0, SP_FOREGROUND);
1491 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1492
1493 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001494 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001495 for (;;) {
1496 struct offload_cmd *cmd = NULL;
1497 stream_callback_event_t event;
1498 bool send_callback = false;
1499
1500 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1501 __func__, list_empty(&out->offload_cmd_list),
1502 out->offload_state);
1503 if (list_empty(&out->offload_cmd_list)) {
1504 ALOGV("%s SLEEPING", __func__);
1505 pthread_cond_wait(&out->offload_cond, &out->lock);
1506 ALOGV("%s RUNNING", __func__);
1507 continue;
1508 }
1509
1510 item = list_head(&out->offload_cmd_list);
1511 cmd = node_to_item(item, struct offload_cmd, node);
1512 list_remove(item);
1513
1514 ALOGVV("%s STATE %d CMD %d out->compr %p",
1515 __func__, out->offload_state, cmd->cmd, out->compr);
1516
1517 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1518 free(cmd);
1519 break;
1520 }
1521
1522 if (out->compr == NULL) {
1523 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001524 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001525 pthread_cond_signal(&out->cond);
1526 continue;
1527 }
1528 out->offload_thread_blocked = true;
1529 pthread_mutex_unlock(&out->lock);
1530 send_callback = false;
1531 switch(cmd->cmd) {
1532 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001533 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001535 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001536 send_callback = true;
1537 event = STREAM_CBK_EVENT_WRITE_READY;
1538 break;
1539 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001540 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301541 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001542 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301543 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001544 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301545 if (ret < 0)
1546 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301547 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301548 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001549 compress_drain(out->compr);
1550 else
1551 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301552 if (ret != -ENETRESET) {
1553 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301554 pthread_mutex_lock(&out->lock);
1555 out->send_new_metadata = 1;
1556 out->send_next_track_params = true;
1557 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301558 event = STREAM_CBK_EVENT_DRAIN_READY;
1559 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1560 } else
1561 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001562 break;
1563 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001564 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001565 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001566 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001567 send_callback = true;
1568 event = STREAM_CBK_EVENT_DRAIN_READY;
1569 break;
1570 default:
1571 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1572 break;
1573 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001574 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001575 out->offload_thread_blocked = false;
1576 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001577 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001578 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001579 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001580 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 free(cmd);
1582 }
1583
1584 pthread_cond_signal(&out->cond);
1585 while (!list_empty(&out->offload_cmd_list)) {
1586 item = list_head(&out->offload_cmd_list);
1587 list_remove(item);
1588 free(node_to_item(item, struct offload_cmd, node));
1589 }
1590 pthread_mutex_unlock(&out->lock);
1591
1592 return NULL;
1593}
1594
1595static int create_offload_callback_thread(struct stream_out *out)
1596{
1597 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1598 list_init(&out->offload_cmd_list);
1599 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1600 offload_thread_loop, out);
1601 return 0;
1602}
1603
1604static int destroy_offload_callback_thread(struct stream_out *out)
1605{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001606 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 stop_compressed_output_l(out);
1608 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1609
1610 pthread_mutex_unlock(&out->lock);
1611 pthread_join(out->offload_thread, (void **) NULL);
1612 pthread_cond_destroy(&out->offload_cond);
1613
1614 return 0;
1615}
1616
Mingming Yin21854652016-04-13 11:54:02 -07001617static bool allow_hdmi_channel_config(struct audio_device *adev,
1618 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001619{
1620 struct listnode *node;
1621 struct audio_usecase *usecase;
1622 bool ret = true;
1623
Mingming Yin21854652016-04-13 11:54:02 -07001624 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1625 ret = false;
1626 goto exit;
1627 }
1628
1629 if (audio_extn_passthru_is_active()) {
1630 ALOGI("%s: Compress audio passthrough is active,"
1631 "no HDMI config change allowed", __func__);
1632 ret = false;
1633 goto exit;
1634 }
1635
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 list_for_each(node, &adev->usecase_list) {
1637 usecase = node_to_item(node, struct audio_usecase, list);
1638 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1639 /*
1640 * If voice call is already existing, do not proceed further to avoid
1641 * disabling/enabling both RX and TX devices, CSD calls, etc.
1642 * Once the voice call done, the HDMI channels can be configured to
1643 * max channels of remaining use cases.
1644 */
1645 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001646 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001647 __func__);
1648 ret = false;
1649 break;
1650 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001651 if (!enable_passthru) {
1652 ALOGV("%s: multi channel playback is active, "
1653 "no change in HDMI channels", __func__);
1654 ret = false;
1655 break;
1656 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001657 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001658 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001659 if (!enable_passthru) {
1660 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1661 ", no change in HDMI channels", __func__,
1662 usecase->stream.out->channel_mask);
1663 ret = false;
1664 break;
1665 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001666 }
1667 }
1668 }
Mingming Yin21854652016-04-13 11:54:02 -07001669 ALOGV("allow hdmi config %d", ret);
1670exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001671 return ret;
1672}
1673
Mingming Yin21854652016-04-13 11:54:02 -07001674static int check_and_set_hdmi_config(struct audio_device *adev,
1675 uint32_t channels,
1676 uint32_t sample_rate,
1677 audio_format_t format,
1678 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001679{
1680 struct listnode *node;
1681 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001682 int32_t factor = 1;
1683 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001684
Mingming Yin21854652016-04-13 11:54:02 -07001685 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1686 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001687
Mingming Yin21854652016-04-13 11:54:02 -07001688 if (channels != adev->cur_hdmi_channels) {
1689 ALOGV("channel does not match current hdmi channels");
1690 config = true;
1691 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001692
Mingming Yin21854652016-04-13 11:54:02 -07001693 if (sample_rate != adev->cur_hdmi_sample_rate) {
1694 ALOGV("sample rate does not match current hdmi sample rate");
1695 config = true;
1696 }
1697
1698 if (format != adev->cur_hdmi_format) {
1699 ALOGV("format does not match current hdmi format");
1700 config = true;
1701 }
1702
1703 /* TBD - add check for bit width */
1704 if (!config) {
1705 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001706 return 0;
1707 }
1708
Mingming Yin21854652016-04-13 11:54:02 -07001709 if (enable_passthru &&
1710 (format == AUDIO_FORMAT_E_AC3)) {
1711 ALOGV("factor 4 for E_AC3 passthru");
1712 factor = 4;
1713 }
1714
1715 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1716 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001717 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001718 adev->cur_hdmi_format = format;
1719 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001720
1721 /*
1722 * Deroute all the playback streams routed to HDMI so that
1723 * the back end is deactivated. Note that backend will not
1724 * be deactivated if any one stream is connected to it.
1725 */
1726 list_for_each(node, &adev->usecase_list) {
1727 usecase = node_to_item(node, struct audio_usecase, list);
1728 if (usecase->type == PCM_PLAYBACK &&
1729 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001730 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001731 }
1732 }
1733
Mingming Yin21854652016-04-13 11:54:02 -07001734 bool was_active = audio_extn_keep_alive_is_active();
1735 if (was_active)
1736 audio_extn_keep_alive_stop();
1737
Eric Laurent07eeafd2013-10-06 12:52:49 -07001738 /*
1739 * Enable all the streams disabled above. Now the HDMI backend
1740 * will be activated with new channel configuration
1741 */
1742 list_for_each(node, &adev->usecase_list) {
1743 usecase = node_to_item(node, struct audio_usecase, list);
1744 if (usecase->type == PCM_PLAYBACK &&
1745 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001746 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001747 }
1748 }
1749
Mingming Yin21854652016-04-13 11:54:02 -07001750 if (was_active)
1751 audio_extn_keep_alive_start();
1752
Eric Laurent07eeafd2013-10-06 12:52:49 -07001753 return 0;
1754}
1755
Mingming Yin21854652016-04-13 11:54:02 -07001756/* called with out lock taken */
1757static int check_and_set_hdmi_backend(struct stream_out *out)
1758{
1759 struct audio_device *adev = out->dev;
1760 int ret;
1761 bool enable_passthru = false;
1762
1763 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1764 return -1;
1765
1766 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1767
1768 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301769 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001770 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301771 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001772 }
1773
1774 /* Check if change in HDMI channel config is allowed */
1775 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1776 return -EPERM;
1777 }
1778
1779 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1780 uint32_t channels;
1781 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1782
1783 if (enable_passthru) {
1784 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301785 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001786 }
1787
1788 /* For pass through case, the backend should be configured as stereo */
1789 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1790 out->compr_config.codec->ch_in;
1791
1792 ret = check_and_set_hdmi_config(adev, channels,
1793 out->sample_rate, out->format,
1794 enable_passthru);
1795 } else
1796 ret = check_and_set_hdmi_config(adev, out->config.channels,
1797 out->config.rate,
1798 out->format,
1799 false);
1800 return ret;
1801}
1802
1803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804static int stop_output_stream(struct stream_out *out)
1805{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301806 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 struct audio_usecase *uc_info;
1808 struct audio_device *adev = out->dev;
1809
Eric Laurent994a6932013-07-17 11:51:42 -07001810 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 uc_info = get_usecase_from_list(adev, out->usecase);
1813 if (uc_info == NULL) {
1814 ALOGE("%s: Could not find the usecase (%d) in the list",
1815 __func__, out->usecase);
1816 return -EINVAL;
1817 }
1818
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001819 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301820 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001821 if (adev->visualizer_stop_output != NULL)
1822 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001823
1824 audio_extn_dts_remove_state_notifier_node(out->usecase);
1825
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001826 if (adev->offload_effects_stop_output != NULL)
1827 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1828 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001829
Eric Laurent150dbfe2013-02-27 14:31:02 -08001830 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001831 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832
1833 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001834 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001836 list_remove(&uc_info->list);
1837 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001839 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301840 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001841 ALOGV("Disable passthrough , reset mixer to pcm");
1842 /* NO_PASSTHROUGH */
1843 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001844
Mingming Yin21854652016-04-13 11:54:02 -07001845 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001846 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1847 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001848
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301849 /* Must be called after removing the usecase from list */
1850 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1851 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1852 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1853 DEFAULT_HDMI_OUT_FORMAT,
1854 false);
Eric Laurent994a6932013-07-17 11:51:42 -07001855 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 return ret;
1857}
1858
1859int start_output_stream(struct stream_out *out)
1860{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 struct audio_usecase *uc_info;
1863 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301864 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001866 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1867 ret = -EINVAL;
1868 goto error_config;
1869 }
1870
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301871 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1872 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1873 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301874
Naresh Tanniru80659832014-06-04 18:17:56 +05301875 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301876 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301877 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301878 goto error_config;
1879 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301880
Eric Laurentb23d5282013-05-14 15:27:20 -07001881 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 if (out->pcm_device_id < 0) {
1883 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1884 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001885 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001886 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 }
1888
1889 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001890
1891 if (!uc_info) {
1892 ret = -ENOMEM;
1893 goto error_config;
1894 }
1895
Mingming Yin21854652016-04-13 11:54:02 -07001896 /* This must be called before adding this usecase to the list */
1897 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1898 /* This call can fail if compress pass thru is already active */
1899 check_and_set_hdmi_backend(out);
1900 }
1901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902 uc_info->id = out->usecase;
1903 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001904 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 uc_info->devices = out->devices;
1906 uc_info->in_snd_device = SND_DEVICE_NONE;
1907 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001908 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301910 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1911 adev->perf_lock_opts,
1912 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001913 select_devices(adev, out->usecase);
1914
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001915 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1916 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001917 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001918 unsigned int flags = PCM_OUT;
1919 unsigned int pcm_open_retry_count = 0;
1920 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1921 flags |= PCM_MMAP | PCM_NOIRQ;
1922 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1923 } else
1924 flags |= PCM_MONOTONIC;
1925
1926 while (1) {
1927 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1928 flags, &out->config);
1929 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1930 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1931 if (out->pcm != NULL) {
1932 pcm_close(out->pcm);
1933 out->pcm = NULL;
1934 }
1935 if (pcm_open_retry_count-- == 0) {
1936 ret = -EIO;
1937 goto error_open;
1938 }
1939 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1940 continue;
1941 }
1942 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001944
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001945 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1946 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001947
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001948 ALOGV("%s: pcm_prepare", __func__);
1949 if (pcm_is_ready(out->pcm)) {
1950 ret = pcm_prepare(out->pcm);
1951 if (ret < 0) {
1952 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1953 pcm_close(out->pcm);
1954 out->pcm = NULL;
1955 goto error_open;
1956 }
1957 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001958 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001959 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1960 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001962 out->compr = compress_open(adev->snd_card,
1963 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 COMPRESS_IN, &out->compr_config);
1965 if (out->compr && !is_compress_ready(out->compr)) {
1966 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1967 compress_close(out->compr);
1968 out->compr = NULL;
1969 ret = -EIO;
1970 goto error_open;
1971 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301972 /* compress_open sends params of the track, so reset the flag here */
1973 out->is_compr_metadata_avail = false;
1974
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001975 if (out->offload_callback)
1976 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001977
Fred Oh3f43e742015-03-04 18:42:34 -08001978 /* Since small bufs uses blocking writes, a write will be blocked
1979 for the default max poll time (20s) in the event of an SSR.
1980 Reduce the poll time to observe and deal with SSR faster.
1981 */
Ashish Jain5106d362016-05-11 19:23:33 +05301982 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001983 compress_set_max_poll_wait(out->compr, 1000);
1984 }
1985
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001986 audio_extn_dts_create_state_notifier_node(out->usecase);
1987 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1988 popcount(out->channel_mask),
1989 out->playback_started);
1990
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001991#ifdef DS1_DOLBY_DDP_ENABLED
1992 if (audio_extn_is_dolby_format(out->format))
1993 audio_extn_dolby_send_ddp_endp_params(adev);
1994#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301995 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001996 if (adev->visualizer_start_output != NULL)
1997 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1998 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301999 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002000 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302003 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002004 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302008 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002010error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302011 /*
2012 * sleep 50ms to allow sufficient time for kernel
2013 * drivers to recover incases like SSR.
2014 */
2015 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002016 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017}
2018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019static int check_input_parameters(uint32_t sample_rate,
2020 audio_format_t format,
2021 int channel_count)
2022{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002023 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302025 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2026 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2027 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002028 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302029 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002030
2031 switch (channel_count) {
2032 case 1:
2033 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302034 case 3:
2035 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002036 case 6:
2037 break;
2038 default:
2039 ret = -EINVAL;
2040 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041
2042 switch (sample_rate) {
2043 case 8000:
2044 case 11025:
2045 case 12000:
2046 case 16000:
2047 case 22050:
2048 case 24000:
2049 case 32000:
2050 case 44100:
2051 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302052 case 96000:
2053 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 break;
2055 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002056 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 }
2058
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002059 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060}
2061
2062static size_t get_input_buffer_size(uint32_t sample_rate,
2063 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002064 int channel_count,
2065 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066{
2067 size_t size = 0;
2068
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002069 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2070 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002072 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002073 if (is_low_latency)
2074 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302075
2076 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002078 /* make sure the size is multiple of 32 bytes
2079 * At 48 kHz mono 16-bit PCM:
2080 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2081 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2082 */
2083 size += 0x1f;
2084 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002085
2086 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087}
2088
Ashish Jain5106d362016-05-11 19:23:33 +05302089static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2090{
2091 uint64_t actual_frames_rendered = 0;
2092 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2093
2094 /* This adjustment accounts for buffering after app processor.
2095 * It is based on estimated DSP latency per use case, rather than exact.
2096 */
2097 int64_t platform_latency = platform_render_latency(out->usecase) *
2098 out->sample_rate / 1000000LL;
2099
2100 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2101 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2102 * hence only estimate.
2103 */
2104 int64_t signed_frames = out->written - kernel_buffer_size;
2105
2106 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2107
2108 if (signed_frames > 0)
2109 actual_frames_rendered = signed_frames;
2110
2111 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2112 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2113 (long long int)out->written, (int)kernel_buffer_size,
2114 audio_bytes_per_sample(out->compr_config.codec->format),
2115 popcount(out->channel_mask));
2116
2117 return actual_frames_rendered;
2118}
2119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2121{
2122 struct stream_out *out = (struct stream_out *)stream;
2123
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125}
2126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002127static int out_set_sample_rate(struct audio_stream *stream __unused,
2128 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129{
2130 return -ENOSYS;
2131}
2132
2133static size_t out_get_buffer_size(const struct audio_stream *stream)
2134{
2135 struct stream_out *out = (struct stream_out *)stream;
2136
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002137 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002139 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2140 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302141 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
2142 return out->compr_pcm_config.hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002144 return out->config.period_size *
2145 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146}
2147
2148static uint32_t out_get_channels(const struct audio_stream *stream)
2149{
2150 struct stream_out *out = (struct stream_out *)stream;
2151
2152 return out->channel_mask;
2153}
2154
2155static audio_format_t out_get_format(const struct audio_stream *stream)
2156{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 struct stream_out *out = (struct stream_out *)stream;
2158
2159 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160}
2161
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002162static int out_set_format(struct audio_stream *stream __unused,
2163 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164{
2165 return -ENOSYS;
2166}
2167
2168static int out_standby(struct audio_stream *stream)
2169{
2170 struct stream_out *out = (struct stream_out *)stream;
2171 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302173 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2174 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002175 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2176 /* Ignore standby in case of voip call because the voip output
2177 * stream is closed in adev_close_output_stream()
2178 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302179 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002180 return 0;
2181 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002183 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002185 if (adev->adm_deregister_stream)
2186 adev->adm_deregister_stream(adev->adm_data, out->handle);
2187
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 */
2559 out->written += bytes / (out->config.channels * sizeof(short));
2560 ALOGD(" %s: sound card is not active/SSR state", __func__);
2561 ret= -EIO;
2562 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302563 }
2564 }
2565
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302566 if (audio_extn_passthru_should_drop_data(out)) {
2567 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2568 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2569 out_get_sample_rate(&out->stream.common));
2570 goto exit;
2571 }
2572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002574 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002575 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002576 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2577 ret = voice_extn_compress_voip_start_output_stream(out);
2578 else
2579 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002580 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002581 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002583 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 goto exit;
2585 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002586
2587 if (last_known_cal_step != -1) {
2588 ALOGD("%s: retry previous failed cal level set", __func__);
2589 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2590 }
2591
vivek mehta446c3962015-09-14 10:57:35 -07002592 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002593 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595
Ashish Jain81eb2a82015-05-13 10:52:34 +05302596 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002597 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302598 adev->is_channel_status_set = true;
2599 }
2600
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002601 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002602 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002603 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002604 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002605 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2606 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302607 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2608 ALOGD("copl(%p):send next track params in gapless", out);
2609 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2610 out->send_next_track_params = false;
2611 out->is_compr_metadata_avail = false;
2612 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002613 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302614 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
2615 (out->compr_pcm_config.convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002616
Ashish Jainf1eaa582016-05-23 20:54:24 +05302617 if ((bytes > out->compr_pcm_config.hal_fragment_size)) {
2618 ALOGW("Error written bytes %zu > %d (fragment_size)",
2619 bytes, out->compr_pcm_config.hal_fragment_size);
2620 pthread_mutex_unlock(&out->lock);
2621 return -EINVAL;
2622 } else {
2623 audio_format_t dst_format = out->compr_pcm_config.hal_op_format;
2624 audio_format_t src_format = out->compr_pcm_config.hal_ip_format;
2625
2626 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2627 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2628
2629 memcpy_by_audio_format(out->compr_pcm_config.convert_buffer,
2630 dst_format,
2631 buffer,
2632 src_format,
2633 frames);
2634
2635 ret = compress_write(out->compr, out->compr_pcm_config.convert_buffer,
2636 bytes_to_write);
2637
2638 /*Convert written bytes in audio flinger format*/
2639 if (ret > 0)
2640 ret = ((ret * format_to_bitwidth_table[out->format]) /
2641 format_to_bitwidth_table[dst_format]);
2642 }
2643 } else
2644 ret = compress_write(out->compr, buffer, bytes);
2645
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302646 if (ret < 0)
2647 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302648 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002649 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302650 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002651 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302652 } else if (-ENETRESET == ret) {
2653 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2654 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2655 pthread_mutex_unlock(&out->lock);
2656 out_standby(&out->stream.common);
2657 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 }
Ashish Jain5106d362016-05-11 19:23:33 +05302659 if ( ret == (ssize_t)bytes && !out->non_blocking)
2660 out->written += bytes;
2661
Naresh Tanniru80659832014-06-04 18:17:56 +05302662 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002664 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002665 out->playback_started = 1;
2666 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002667
2668 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2669 popcount(out->channel_mask),
2670 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 }
2672 pthread_mutex_unlock(&out->lock);
2673 return ret;
2674 } else {
2675 if (out->pcm) {
2676 if (out->muted)
2677 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002678
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302679 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002680
2681 if (adev->adm_request_focus)
2682 adev->adm_request_focus(adev->adm_data, out->handle);
2683
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002684 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2685 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2686 else
2687 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002688
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302689 if (ret < 0)
2690 ret = -errno;
2691 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002692 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002693
2694 if (adev->adm_abandon_focus)
2695 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 }
2698
2699exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302700 /* ToDo: There may be a corner case when SSR happens back to back during
2701 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302702 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302703 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302704 }
2705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 pthread_mutex_unlock(&out->lock);
2707
2708 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002709 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002710 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302711 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302712 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302713 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302714 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302715 out->standby = true;
2716 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302718 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302719 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 }
2721 return bytes;
2722}
2723
2724static int out_get_render_position(const struct audio_stream_out *stream,
2725 uint32_t *dsp_frames)
2726{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002727 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302728 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002729
2730 if (dsp_frames == NULL)
2731 return -EINVAL;
2732
2733 *dsp_frames = 0;
2734 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002735 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302736
2737 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2738 * this operation and adev_close_output_stream(where out gets reset).
2739 */
2740 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2741 *dsp_frames = get_actual_pcm_frames_rendered(out);
2742 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2743 return 0;
2744 }
2745
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002746 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302747 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302748 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002749 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302750 if (ret < 0)
2751 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302753 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002754 }
2755 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302756 if (-ENETRESET == ret) {
2757 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2758 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2759 return -EINVAL;
2760 } else if(ret < 0) {
2761 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2762 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302763 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2764 /*
2765 * Handle corner case where compress session is closed during SSR
2766 * and timestamp is queried
2767 */
2768 ALOGE(" ERROR: sound card not active, return error");
2769 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302770 } else {
2771 return 0;
2772 }
Zhou Song32a556e2015-05-05 10:46:56 +08002773 } else if (audio_is_linear_pcm(out->format)) {
2774 *dsp_frames = out->written;
2775 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 } else
2777 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778}
2779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002780static int out_add_audio_effect(const struct audio_stream *stream __unused,
2781 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782{
2783 return 0;
2784}
2785
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002786static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2787 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788{
2789 return 0;
2790}
2791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002792static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2793 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794{
2795 return -EINVAL;
2796}
2797
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002798static int out_get_presentation_position(const struct audio_stream_out *stream,
2799 uint64_t *frames, struct timespec *timestamp)
2800{
2801 struct stream_out *out = (struct stream_out *)stream;
2802 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002803 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002804
Ashish Jain5106d362016-05-11 19:23:33 +05302805 /* below piece of code is not guarded against any lock because audioFliner serializes
2806 * this operation and adev_close_output_stream( where out gets reset).
2807 */
2808 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2809 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2810 *frames = get_actual_pcm_frames_rendered(out);
2811 /* this is the best we can do */
2812 clock_gettime(CLOCK_MONOTONIC, timestamp);
2813 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2814 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2815 return 0;
2816 }
2817
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002818 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002819
Ashish Jain5106d362016-05-11 19:23:33 +05302820 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2821 ret = compress_get_tstamp(out->compr, &dsp_frames,
2822 &out->sample_rate);
2823 ALOGVV("%s rendered frames %ld sample_rate %d",
2824 __func__, dsp_frames, out->sample_rate);
2825 *frames = dsp_frames;
2826 if (ret < 0)
2827 ret = -errno;
2828 if (-ENETRESET == ret) {
2829 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2830 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2831 ret = -EINVAL;
2832 } else
2833 ret = 0;
2834 /* this is the best we can do */
2835 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002836 } else {
2837 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002838 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002839 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2840 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002841 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002842 // This adjustment accounts for buffering after app processor.
2843 // It is based on estimated DSP latency per use case, rather than exact.
2844 signed_frames -=
2845 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2846
Eric Laurent949a0892013-09-20 09:20:13 -07002847 // It would be unusual for this value to be negative, but check just in case ...
2848 if (signed_frames >= 0) {
2849 *frames = signed_frames;
2850 ret = 0;
2851 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002852 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302853 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2854 *frames = out->written;
2855 clock_gettime(CLOCK_MONOTONIC, timestamp);
2856 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002857 }
2858 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002859 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002860 return ret;
2861}
2862
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863static int out_set_callback(struct audio_stream_out *stream,
2864 stream_callback_t callback, void *cookie)
2865{
2866 struct stream_out *out = (struct stream_out *)stream;
2867
2868 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002869 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->offload_callback = callback;
2871 out->offload_cookie = cookie;
2872 pthread_mutex_unlock(&out->lock);
2873 return 0;
2874}
2875
2876static int out_pause(struct audio_stream_out* stream)
2877{
2878 struct stream_out *out = (struct stream_out *)stream;
2879 int status = -ENOSYS;
2880 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002881 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002882 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002883 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302885 struct audio_device *adev = out->dev;
2886 int snd_scard_state = get_snd_card_state(adev);
2887
2888 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2889 status = compress_pause(out->compr);
2890
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002892
Mingming Yin21854652016-04-13 11:54:02 -07002893 if (audio_extn_passthru_is_active()) {
2894 ALOGV("offload use case, pause passthru");
2895 audio_extn_passthru_on_pause(out);
2896 }
2897
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302898 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002899 audio_extn_dts_notify_playback_state(out->usecase, 0,
2900 out->sample_rate, popcount(out->channel_mask),
2901 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 }
2903 pthread_mutex_unlock(&out->lock);
2904 }
2905 return status;
2906}
2907
2908static int out_resume(struct audio_stream_out* stream)
2909{
2910 struct stream_out *out = (struct stream_out *)stream;
2911 int status = -ENOSYS;
2912 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002913 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002914 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002916 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302918 struct audio_device *adev = out->dev;
2919 int snd_scard_state = get_snd_card_state(adev);
2920
Mingming Yin21854652016-04-13 11:54:02 -07002921 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2922 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2923 pthread_mutex_lock(&out->dev->lock);
2924 ALOGV("offload resume, check and set hdmi backend again");
2925 check_and_set_hdmi_backend(out);
2926 pthread_mutex_unlock(&out->dev->lock);
2927 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302928 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002929 }
2930 if (!status) {
2931 out->offload_state = OFFLOAD_STATE_PLAYING;
2932 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302933 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002934 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2935 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 }
2937 pthread_mutex_unlock(&out->lock);
2938 }
2939 return status;
2940}
2941
2942static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2943{
2944 struct stream_out *out = (struct stream_out *)stream;
2945 int status = -ENOSYS;
2946 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002947 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002948 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2950 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2951 else
2952 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2953 pthread_mutex_unlock(&out->lock);
2954 }
2955 return status;
2956}
2957
2958static int out_flush(struct audio_stream_out* stream)
2959{
2960 struct stream_out *out = (struct stream_out *)stream;
2961 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002962 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002963 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002964 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002965 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302966 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002968 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 return 0;
2970 }
2971 return -ENOSYS;
2972}
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974/** audio_stream_in implementation **/
2975static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2976{
2977 struct stream_in *in = (struct stream_in *)stream;
2978
2979 return in->config.rate;
2980}
2981
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002982static int in_set_sample_rate(struct audio_stream *stream __unused,
2983 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984{
2985 return -ENOSYS;
2986}
2987
2988static size_t in_get_buffer_size(const struct audio_stream *stream)
2989{
2990 struct stream_in *in = (struct stream_in *)stream;
2991
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002992 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2993 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002994 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2995 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002996
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002997 return in->config.period_size *
2998 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999}
3000
3001static uint32_t in_get_channels(const struct audio_stream *stream)
3002{
3003 struct stream_in *in = (struct stream_in *)stream;
3004
3005 return in->channel_mask;
3006}
3007
3008static audio_format_t in_get_format(const struct audio_stream *stream)
3009{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003010 struct stream_in *in = (struct stream_in *)stream;
3011
3012 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013}
3014
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003015static int in_set_format(struct audio_stream *stream __unused,
3016 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017{
3018 return -ENOSYS;
3019}
3020
3021static int in_standby(struct audio_stream *stream)
3022{
3023 struct stream_in *in = (struct stream_in *)stream;
3024 struct audio_device *adev = in->dev;
3025 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303026 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3027 stream, in->usecase, use_case_table[in->usecase]);
3028
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003029 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3030 /* Ignore standby in case of voip call because the voip input
3031 * stream is closed in adev_close_input_stream()
3032 */
3033 ALOGV("%s: Ignore Standby in VOIP call", __func__);
3034 return status;
3035 }
3036
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003037 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003038 if (!in->standby && in->is_st_session) {
3039 ALOGD("%s: sound trigger pcm stop lab", __func__);
3040 audio_extn_sound_trigger_stop_lab(in);
3041 in->standby = 1;
3042 }
3043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003045 if (adev->adm_deregister_stream)
3046 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3047
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003048 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003050 if (in->pcm) {
3051 pcm_close(in->pcm);
3052 in->pcm = NULL;
3053 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003055 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 }
3057 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003058 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 return status;
3060}
3061
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003062static int in_dump(const struct audio_stream *stream __unused,
3063 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064{
3065 return 0;
3066}
3067
3068static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3069{
3070 struct stream_in *in = (struct stream_in *)stream;
3071 struct audio_device *adev = in->dev;
3072 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003074 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303076 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 parms = str_parms_create_str(kvpairs);
3078
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303079 if (!parms)
3080 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003081 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003082 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003083
3084 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3085 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086 val = atoi(value);
3087 /* no audio source uses val == 0 */
3088 if ((in->source != val) && (val != 0)) {
3089 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003090 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3091 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3092 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003093 (in->config.rate == 8000 || in->config.rate == 16000 ||
3094 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003095 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003096 err = voice_extn_compress_voip_open_input_stream(in);
3097 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003098 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003099 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003100 }
3101 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 }
3103 }
3104
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003105 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3106 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003108 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 in->device = val;
3110 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003111 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003112 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 }
3114 }
3115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003117 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118
3119 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303120error:
Eric Laurent994a6932013-07-17 11:51:42 -07003121 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 return ret;
3123}
3124
3125static char* in_get_parameters(const struct audio_stream *stream,
3126 const char *keys)
3127{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003128 struct stream_in *in = (struct stream_in *)stream;
3129 struct str_parms *query = str_parms_create_str(keys);
3130 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003131 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003132
3133 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003134 if (reply) {
3135 str_parms_destroy(reply);
3136 }
3137 if (query) {
3138 str_parms_destroy(query);
3139 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003140 ALOGE("in_get_parameters: failed to create query or reply");
3141 return NULL;
3142 }
3143
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003144 ALOGV("%s: enter: keys - %s", __func__, keys);
3145
3146 voice_extn_in_get_parameters(in, query, reply);
3147
3148 str = str_parms_to_str(reply);
3149 str_parms_destroy(query);
3150 str_parms_destroy(reply);
3151
3152 ALOGV("%s: exit: returns - %s", __func__, str);
3153 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154}
3155
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003156static int in_set_gain(struct audio_stream_in *stream __unused,
3157 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158{
3159 return 0;
3160}
3161
3162static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3163 size_t bytes)
3164{
3165 struct stream_in *in = (struct stream_in *)stream;
3166 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303167 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303168 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303169 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003171 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303172
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003173 if (in->is_st_session) {
3174 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3175 /* Read from sound trigger HAL */
3176 audio_extn_sound_trigger_read(in, buffer, bytes);
3177 pthread_mutex_unlock(&in->lock);
3178 return bytes;
3179 }
3180
Ashish Jainbbce4322016-02-16 13:25:27 +05303181 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003182 ALOGD(" %s: sound card is not active/SSR state", __func__);
3183 ret= -EIO;;
3184 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303185 }
3186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003188 pthread_mutex_lock(&adev->lock);
3189 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3190 ret = voice_extn_compress_voip_start_input_stream(in);
3191 else
3192 ret = start_input_stream(in);
3193 pthread_mutex_unlock(&adev->lock);
3194 if (ret != 0) {
3195 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 }
3197 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003198 if (adev->adm_register_input_stream)
3199 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003202 if (adev->adm_request_focus)
3203 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303206 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003207 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303208 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003209 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303210 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003211 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303212 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003213 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303214 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3215 if (bytes % 4 == 0) {
3216 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3217 int_buf_stream = buffer;
3218 for (size_t itt=0; itt < bytes/4 ; itt++) {
3219 int_buf_stream[itt] >>= 8;
3220 }
3221 } else {
3222 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3223 ret = -EINVAL;
3224 goto exit;
3225 }
3226 } if (ret < 0) {
3227 ret = -errno;
3228 }
3229 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 }
3231
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003232 if (adev->adm_abandon_focus)
3233 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235 /*
3236 * Instead of writing zeroes here, we could trust the hardware
3237 * to always provide zeroes when muted.
3238 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303239 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3240 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241 memset(buffer, 0, bytes);
3242
3243exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303244 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303245 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003246 if (-ENETRESET == ret)
3247 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 pthread_mutex_unlock(&in->lock);
3250
3251 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303252 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303253 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303254 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303255 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303256 in->standby = true;
3257 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303258 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003260 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303261 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303262 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 }
3264 return bytes;
3265}
3266
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003267static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268{
3269 return 0;
3270}
3271
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003272static int add_remove_audio_effect(const struct audio_stream *stream,
3273 effect_handle_t effect,
3274 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003276 struct stream_in *in = (struct stream_in *)stream;
3277 int status = 0;
3278 effect_descriptor_t desc;
3279
3280 status = (*effect)->get_descriptor(effect, &desc);
3281 if (status != 0)
3282 return status;
3283
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003284 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003285 pthread_mutex_lock(&in->dev->lock);
3286 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3287 in->enable_aec != enable &&
3288 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3289 in->enable_aec = enable;
3290 if (!in->standby)
3291 select_devices(in->dev, in->usecase);
3292 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003293 if (in->enable_ns != enable &&
3294 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3295 in->enable_ns = enable;
3296 if (!in->standby)
3297 select_devices(in->dev, in->usecase);
3298 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003299 pthread_mutex_unlock(&in->dev->lock);
3300 pthread_mutex_unlock(&in->lock);
3301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 return 0;
3303}
3304
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003305static int in_add_audio_effect(const struct audio_stream *stream,
3306 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
Eric Laurent994a6932013-07-17 11:51:42 -07003308 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003309 return add_remove_audio_effect(stream, effect, true);
3310}
3311
3312static int in_remove_audio_effect(const struct audio_stream *stream,
3313 effect_handle_t effect)
3314{
Eric Laurent994a6932013-07-17 11:51:42 -07003315 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003316 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317}
3318
3319static int adev_open_output_stream(struct audio_hw_device *dev,
3320 audio_io_handle_t handle,
3321 audio_devices_t devices,
3322 audio_output_flags_t flags,
3323 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003324 struct audio_stream_out **stream_out,
3325 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326{
3327 struct audio_device *adev = (struct audio_device *)dev;
3328 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303329 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003330 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303333
3334 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3335 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003336 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303337 return -EINVAL;
3338 }
3339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3341
Mingming Yin3a941d42016-02-17 18:08:05 -08003342 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3343 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303344 devices, flags, &out->stream);
3345
3346
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003347 if (!out) {
3348 return -ENOMEM;
3349 }
3350
Haynes Mathew George204045b2015-02-25 20:32:03 -08003351 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003352 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003353 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 if (devices == AUDIO_DEVICE_NONE)
3356 devices = AUDIO_DEVICE_OUT_SPEAKER;
3357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 out->flags = flags;
3359 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003360 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003361 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 out->sample_rate = config->sample_rate;
3363 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3364 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003365 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003366 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003367 out->non_blocking = 0;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303368 out->compr_pcm_config.convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369
Mingming Yin3a941d42016-02-17 18:08:05 -08003370 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3371 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3372 pthread_mutex_lock(&adev->lock);
3373 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3374 ret = read_hdmi_sink_caps(out);
3375 pthread_mutex_unlock(&adev->lock);
3376 if (ret != 0) {
3377 if (ret == -ENOSYS) {
3378 /* ignore and go with default */
3379 ret = 0;
3380 } else {
3381 ALOGE("error reading hdmi sink caps");
3382 goto error_open;
3383 }
3384 }
3385 }
3386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003388 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303389 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3390 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003391 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3392 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3393
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003394 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003395 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3396 /*
3397 * Do not handle stereo output in Multi-channel cases
3398 * Stereo case is handled in normal playback path
3399 */
3400 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3401 ret = AUDIO_CHANNEL_OUT_STEREO;
3402 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003403
3404 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3405 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003406 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003407 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003408 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003409
3410 if (config->sample_rate == 0)
3411 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3412 if (config->channel_mask == 0)
3413 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003414 if (config->format == 0)
3415 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003416
3417 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003418 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003419 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3421 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003423 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003425 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3426 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003427 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003428 ret = voice_extn_compress_voip_open_output_stream(out);
3429 if (ret != 0) {
3430 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3431 __func__, ret);
3432 goto error_open;
3433 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003434 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3435 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3436
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003437 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3438 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3439 ALOGE("%s: Unsupported Offload information", __func__);
3440 ret = -EINVAL;
3441 goto error_open;
3442 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003443
Mingming Yin3a941d42016-02-17 18:08:05 -08003444 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003445 if(config->offload_info.format == 0)
3446 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003447 if (config->offload_info.sample_rate == 0)
3448 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003449 }
3450
Mingming Yin90310102013-11-13 16:57:00 -08003451 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303452 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003453 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003454 ret = -EINVAL;
3455 goto error_open;
3456 }
3457
3458 out->compr_config.codec = (struct snd_codec *)
3459 calloc(1, sizeof(struct snd_codec));
3460
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003461 if (!out->compr_config.codec) {
3462 ret = -ENOMEM;
3463 goto error_open;
3464 }
3465
vivek mehta0ea887a2015-08-26 14:01:20 -07003466 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303467 out->stream.pause = out_pause;
3468 out->stream.flush = out_flush;
3469 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003470 out->usecase = get_offload_usecase(adev, true);
3471 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003472 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003473 out->stream.set_callback = out_set_callback;
3474 out->stream.pause = out_pause;
3475 out->stream.resume = out_resume;
3476 out->stream.drain = out_drain;
3477 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003478 out->usecase = get_offload_usecase(adev, false);
3479 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003480 }
vivek mehta446c3962015-09-14 10:57:35 -07003481
3482 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003483 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3484 config->format == 0 && config->sample_rate == 0 &&
3485 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003486 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003487 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3488 } else {
3489 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3490 ret = -EEXIST;
3491 goto error_open;
3492 }
vivek mehta446c3962015-09-14 10:57:35 -07003493 }
3494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003495 if (config->offload_info.channel_mask)
3496 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003497 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003499 config->offload_info.channel_mask = config->channel_mask;
3500 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003501 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 out->sample_rate = config->offload_info.sample_rate;
3503
Mingming Yin3ee55c62014-08-04 14:23:35 -07003504 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303506 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3507 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3508 audio_extn_dolby_send_ddp_endp_params(adev);
3509 audio_extn_dolby_set_dmid(adev);
3510 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003511
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003513 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003514 out->compr_config.codec->bit_rate =
3515 config->offload_info.bit_rate;
3516 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003517 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303519 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003520 /*TODO: Do we need to change it for passthrough */
3521 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522
Manish Dewangana6fc5442015-08-24 20:30:31 +05303523 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3524 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3525 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3526 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303527
3528 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3529 AUDIO_FORMAT_PCM) {
3530
3531 /*Based on platform support, configure appropriate alsa format for corresponding
3532 *hal input format.
3533 */
3534 out->compr_config.codec->format = hal_format_to_alsa(
3535 config->offload_info.format);
3536
3537 out->compr_pcm_config.hal_op_format = alsa_format_to_hal(
3538 out->compr_config.codec->format);
3539 out->compr_pcm_config.hal_ip_format = out->format;
3540
3541 /*for direct PCM playback populate bit_width based on selected alsa format as
3542 *hal input format and alsa format might differ based on platform support.
3543 */
3544 out->bit_width = audio_bytes_per_sample(
3545 out->compr_pcm_config.hal_op_format) << 3;
3546
3547 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3548
3549 /* Check if alsa session is configured with the same format as HAL input format,
3550 * if not then derive correct fragment size needed to accomodate the
3551 * conversion of HAL input format to alsa format.
3552 */
3553 audio_extn_utils_update_direct_pcm_fragment_size(out);
3554
3555 /*if hal input and output fragment size is different this indicates HAL input format is
3556 *not same as the alsa format
3557 */
3558 if (out->compr_pcm_config.hal_fragment_size != out->compr_config.fragment_size) {
3559 /*Allocate a buffer to convert input data to the alsa configured format.
3560 *size of convert buffer is equal to the size required to hold one fragment size
3561 *worth of pcm data, this is because flinger does not write more than fragment_size
3562 */
3563 out->compr_pcm_config.convert_buffer = calloc(1,out->compr_config.fragment_size);
3564 if (out->compr_pcm_config.convert_buffer == NULL){
3565 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3566 ret = -ENOMEM;
3567 goto error_open;
3568 }
3569 }
3570 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3571 out->compr_config.fragment_size =
3572 audio_extn_passthru_get_buffer_size(&config->offload_info);
3573 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3574 } else {
3575 out->compr_config.fragment_size =
3576 platform_get_compress_offload_buffer_size(&config->offload_info);
3577 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3578 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003579
Amit Shekhar6f461b12014-08-01 14:52:58 -07003580 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303581 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003582
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3584 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003585
Alexy Josephaa54c872014-12-03 02:46:47 -08003586
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003587 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303588 out->send_next_track_params = false;
3589 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003590 out->offload_state = OFFLOAD_STATE_IDLE;
3591 out->playback_started = 0;
3592
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003593 audio_extn_dts_create_state_notifier_node(out->usecase);
3594
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003595 create_offload_callback_thread(out);
3596 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3597 __func__, config->offload_info.version,
3598 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303599
3600 /* Disable gapless if any of the following is true
3601 * passthrough playback
3602 * AV playback
3603 * Direct PCM playback
3604 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303605 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303606 config->offload_info.has_video ||
3607 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3608 check_and_set_gapless_mode(adev, false);
3609 } else
3610 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003611
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303612 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003613 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3614 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003615 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303616 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003617 if (ret != 0) {
3618 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3619 __func__, ret);
3620 goto error_open;
3621 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003622 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3623 if (config->sample_rate == 0)
3624 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3625 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3626 config->sample_rate != 8000) {
3627 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3628 ret = -EINVAL;
3629 goto error_open;
3630 }
3631 out->sample_rate = config->sample_rate;
3632 out->config.rate = config->sample_rate;
3633 if (config->format == AUDIO_FORMAT_DEFAULT)
3634 config->format = AUDIO_FORMAT_PCM_16_BIT;
3635 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3636 config->format = AUDIO_FORMAT_PCM_16_BIT;
3637 ret = -EINVAL;
3638 goto error_open;
3639 }
3640 out->format = config->format;
3641 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3642 out->config = pcm_config_afe_proxy_playback;
3643 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003644 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3645 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3646 out->config = pcm_config_low_latency;
3647 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003648 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003649 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3651 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003653 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3654 format = AUDIO_FORMAT_PCM_16_BIT;
3655 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3656 out->config = pcm_config_deep_buffer;
3657 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003658 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003659 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003660 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003661 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003662 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003663 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 }
3665
Mingming Yin21854652016-04-13 11:54:02 -07003666 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3667 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003668 /* TODO remove this hardcoding and check why width is zero*/
3669 if (out->bit_width == 0)
3670 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003671 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3672 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003673 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303674 out->bit_width, out->channel_mask,
3675 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003676 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3677 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3678 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003679 if(adev->primary_output == NULL)
3680 adev->primary_output = out;
3681 else {
3682 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003683 ret = -EEXIST;
3684 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003685 }
3686 }
3687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 /* Check if this usecase is already existing */
3689 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003690 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3691 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003694 ret = -EEXIST;
3695 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 }
3697 pthread_mutex_unlock(&adev->lock);
3698
3699 out->stream.common.get_sample_rate = out_get_sample_rate;
3700 out->stream.common.set_sample_rate = out_set_sample_rate;
3701 out->stream.common.get_buffer_size = out_get_buffer_size;
3702 out->stream.common.get_channels = out_get_channels;
3703 out->stream.common.get_format = out_get_format;
3704 out->stream.common.set_format = out_set_format;
3705 out->stream.common.standby = out_standby;
3706 out->stream.common.dump = out_dump;
3707 out->stream.common.set_parameters = out_set_parameters;
3708 out->stream.common.get_parameters = out_get_parameters;
3709 out->stream.common.add_audio_effect = out_add_audio_effect;
3710 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3711 out->stream.get_latency = out_get_latency;
3712 out->stream.set_volume = out_set_volume;
3713 out->stream.write = out_write;
3714 out->stream.get_render_position = out_get_render_position;
3715 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003716 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003719 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003720 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721
3722 config->format = out->stream.common.get_format(&out->stream.common);
3723 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3724 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3725
3726 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303727 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003728 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003729
3730 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3731 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3732 popcount(out->channel_mask), out->playback_started);
3733
Eric Laurent994a6932013-07-17 11:51:42 -07003734 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003736
3737error_open:
Ashish Jainf1eaa582016-05-23 20:54:24 +05303738 if (out->compr_pcm_config.convert_buffer)
3739 free(out->compr_pcm_config.convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003740 free(out);
3741 *stream_out = NULL;
3742 ALOGD("%s: exit: ret %d", __func__, ret);
3743 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744}
3745
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003746static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 struct audio_stream_out *stream)
3748{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003749 struct stream_out *out = (struct stream_out *)stream;
3750 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003751 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003752
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303753 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3754
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003755 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303756 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003757 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303758 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003759 if(ret != 0)
3760 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3761 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003762 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003763 out_standby(&stream->common);
3764
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003765 if (is_offload_usecase(out->usecase)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303766 if (out->compr_pcm_config.convert_buffer != NULL)
3767 free(out->compr_pcm_config.convert_buffer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003768 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003770 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003771 if (out->compr_config.codec != NULL)
3772 free(out->compr_config.codec);
3773 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003774
3775 if (adev->voice_tx_output == out)
3776 adev->voice_tx_output = NULL;
3777
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003778 pthread_cond_destroy(&out->cond);
3779 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003781 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782}
3783
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003784static void close_compress_sessions(struct audio_device *adev)
3785{
Mingming Yin7b762e72015-03-04 13:47:32 -08003786 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303787 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003788 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003789 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303790
3791 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003792 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303793 if (is_offload_usecase(usecase->id)) {
3794 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003795 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3796 out = usecase->stream.out;
3797 pthread_mutex_unlock(&adev->lock);
3798 out_standby(&out->stream.common);
3799 pthread_mutex_lock(&adev->lock);
3800 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303801 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003802 }
3803 pthread_mutex_unlock(&adev->lock);
3804}
3805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3807{
3808 struct audio_device *adev = (struct audio_device *)dev;
3809 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003811 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003812 int ret;
3813 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003815 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303818 if (!parms)
3819 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003820 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3821 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303822 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303823 if (strstr(snd_card_status, "OFFLINE")) {
3824 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303825 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003826 //close compress sessions on OFFLINE status
3827 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303828 } else if (strstr(snd_card_status, "ONLINE")) {
3829 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303830 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003831 //send dts hpx license if enabled
3832 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303833 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303834 }
3835
3836 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003837 status = voice_set_parameters(adev, parms);
3838 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003839 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003841 status = platform_set_parameters(adev->platform, parms);
3842 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003843 goto done;
3844
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003845 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3846 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003847 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3849 adev->bluetooth_nrec = true;
3850 else
3851 adev->bluetooth_nrec = false;
3852 }
3853
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003854 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3855 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3857 adev->screen_off = false;
3858 else
3859 adev->screen_off = true;
3860 }
3861
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003862 ret = str_parms_get_int(parms, "rotation", &val);
3863 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003864 bool reverse_speakers = false;
3865 switch(val) {
3866 // FIXME: note that the code below assumes that the speakers are in the correct placement
3867 // relative to the user when the device is rotated 90deg from its default rotation. This
3868 // assumption is device-specific, not platform-specific like this code.
3869 case 270:
3870 reverse_speakers = true;
3871 break;
3872 case 0:
3873 case 90:
3874 case 180:
3875 break;
3876 default:
3877 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003878 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003879 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003880 if (status == 0) {
3881 if (adev->speaker_lr_swap != reverse_speakers) {
3882 adev->speaker_lr_swap = reverse_speakers;
3883 // only update the selected device if there is active pcm playback
3884 struct audio_usecase *usecase;
3885 struct listnode *node;
3886 list_for_each(node, &adev->usecase_list) {
3887 usecase = node_to_item(node, struct audio_usecase, list);
3888 if (usecase->type == PCM_PLAYBACK) {
3889 select_devices(adev, usecase->id);
3890 break;
3891 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003892 }
3893 }
3894 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003895 }
3896
Mingming Yin514a8bc2014-07-29 15:22:21 -07003897 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3898 if (ret >= 0) {
3899 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3900 adev->bt_wb_speech_enabled = true;
3901 else
3902 adev->bt_wb_speech_enabled = false;
3903 }
3904
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003905 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3906 if (ret >= 0) {
3907 val = atoi(value);
3908 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3909 ALOGV("cache new edid");
3910 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003911 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3912 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07003913 /*
3914 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3915 * Per AudioPolicyManager, USB device is higher priority than WFD.
3916 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3917 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3918 * starting voice call on USB
3919 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003920 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3921 if (ret >= 0) {
3922 audio_extn_usb_add_device(val, atoi(value));
3923 }
vivek mehta344576a2016-04-12 18:56:03 -07003924 ALOGV("detected USB connect .. disable proxy");
3925 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003926 }
3927 }
3928
3929 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3930 if (ret >= 0) {
3931 val = atoi(value);
3932 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3933 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08003934 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003935 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3936 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
3937 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3938 if (ret >= 0) {
3939 audio_extn_usb_remove_device(val, atoi(value));
3940 }
vivek mehta344576a2016-04-12 18:56:03 -07003941 ALOGV("detected USB disconnect .. enable proxy");
3942 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003943 }
3944 }
3945
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003946 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003947
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003948done:
3949 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003950 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303951error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003952 ALOGV("%s: exit with code(%d)", __func__, status);
3953 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954}
3955
3956static char* adev_get_parameters(const struct audio_hw_device *dev,
3957 const char *keys)
3958{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003959 struct audio_device *adev = (struct audio_device *)dev;
3960 struct str_parms *reply = str_parms_create();
3961 struct str_parms *query = str_parms_create_str(keys);
3962 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303963 char value[256] = {0};
3964 int ret = 0;
3965
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003966 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003967 if (reply) {
3968 str_parms_destroy(reply);
3969 }
3970 if (query) {
3971 str_parms_destroy(query);
3972 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003973 ALOGE("adev_get_parameters: failed to create query or reply");
3974 return NULL;
3975 }
3976
Naresh Tannirud7205b62014-06-20 02:54:48 +05303977 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3978 sizeof(value));
3979 if (ret >=0) {
3980 int val = 1;
3981 pthread_mutex_lock(&adev->snd_card_status.lock);
3982 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3983 val = 0;
3984 pthread_mutex_unlock(&adev->snd_card_status.lock);
3985 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3986 goto exit;
3987 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003988
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003989 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003990 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003991 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003992 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303993 pthread_mutex_unlock(&adev->lock);
3994
Naresh Tannirud7205b62014-06-20 02:54:48 +05303995exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003996 str = str_parms_to_str(reply);
3997 str_parms_destroy(query);
3998 str_parms_destroy(reply);
3999
4000 ALOGV("%s: exit: returns - %s", __func__, str);
4001 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002}
4003
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004004static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005{
4006 return 0;
4007}
4008
4009static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4010{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004011 int ret;
4012 struct audio_device *adev = (struct audio_device *)dev;
4013 pthread_mutex_lock(&adev->lock);
4014 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004015 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004016 pthread_mutex_unlock(&adev->lock);
4017 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018}
4019
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004020static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4021 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022{
4023 return -ENOSYS;
4024}
4025
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004026static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4027 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004028{
4029 return -ENOSYS;
4030}
4031
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004032static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4033 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034{
4035 return -ENOSYS;
4036}
4037
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004038static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4039 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040{
4041 return -ENOSYS;
4042}
4043
4044static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4045{
4046 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048 pthread_mutex_lock(&adev->lock);
4049 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004050 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004052 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004053 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004054 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004055 adev->current_call_output = NULL;
4056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 }
4058 pthread_mutex_unlock(&adev->lock);
4059 return 0;
4060}
4061
4062static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4063{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004064 int ret;
4065
4066 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004067 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004068 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4069 pthread_mutex_unlock(&adev->lock);
4070
4071 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072}
4073
4074static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4075{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004076 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 return 0;
4078}
4079
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004080static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081 const struct audio_config *config)
4082{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004083 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004085 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4086 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087}
4088
4089static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004090 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091 audio_devices_t devices,
4092 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004093 struct audio_stream_in **stream_in,
4094 audio_input_flags_t flags __unused,
4095 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004096 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097{
4098 struct audio_device *adev = (struct audio_device *)dev;
4099 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004100 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004101 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004102 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304105 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4106 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109
4110 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004111
4112 if (!in) {
4113 ALOGE("failed to allocate input stream");
4114 return -ENOMEM;
4115 }
4116
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304117 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304118 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4119 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004120 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004121 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123 in->stream.common.get_sample_rate = in_get_sample_rate;
4124 in->stream.common.set_sample_rate = in_set_sample_rate;
4125 in->stream.common.get_buffer_size = in_get_buffer_size;
4126 in->stream.common.get_channels = in_get_channels;
4127 in->stream.common.get_format = in_get_format;
4128 in->stream.common.set_format = in_set_format;
4129 in->stream.common.standby = in_standby;
4130 in->stream.common.dump = in_dump;
4131 in->stream.common.set_parameters = in_set_parameters;
4132 in->stream.common.get_parameters = in_get_parameters;
4133 in->stream.common.add_audio_effect = in_add_audio_effect;
4134 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4135 in->stream.set_gain = in_set_gain;
4136 in->stream.read = in_read;
4137 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4138
4139 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004140 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 in->standby = 1;
4143 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004144 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004145 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146
4147 /* Update config params with the requested sample rate and channels */
4148 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004149 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4150 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4151 is_low_latency = true;
4152#if LOW_LATENCY_CAPTURE_USE_CASE
4153 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4154#endif
4155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004158 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304159 in->bit_width = 16;
4160 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004162 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304163 if (adev->mode != AUDIO_MODE_IN_CALL) {
4164 ret = -EINVAL;
4165 goto err_open;
4166 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004167 if (config->sample_rate == 0)
4168 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4169 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4170 config->sample_rate != 8000) {
4171 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4172 ret = -EINVAL;
4173 goto err_open;
4174 }
4175 if (config->format == AUDIO_FORMAT_DEFAULT)
4176 config->format = AUDIO_FORMAT_PCM_16_BIT;
4177 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4178 config->format = AUDIO_FORMAT_PCM_16_BIT;
4179 ret = -EINVAL;
4180 goto err_open;
4181 }
4182
4183 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4184 in->config = pcm_config_afe_proxy_record;
4185 in->config.channels = channel_count;
4186 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304187 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304188 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4189 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004190 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004191 audio_extn_compr_cap_format_supported(config->format) &&
4192 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004193 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004194 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304195 /* restrict 24 bit capture for unprocessed source only
4196 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4197 */
4198 if (config->format == AUDIO_FORMAT_DEFAULT) {
4199 config->format = AUDIO_FORMAT_PCM_16_BIT;
4200 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4201 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4202 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4203 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4204 bool ret_error = false;
4205 in->bit_width = 24;
4206 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4207 from HAL is 24_packed and 8_24
4208 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4209 24_packed return error indicating supported format is 24_packed
4210 *> In case of any other source requesting 24 bit or float return error
4211 indicating format supported is 16 bit only.
4212
4213 on error flinger will retry with supported format passed
4214 */
4215 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4216 (source != AUDIO_SOURCE_CAMCORDER)) {
4217 config->format = AUDIO_FORMAT_PCM_16_BIT;
4218 if( config->sample_rate > 48000)
4219 config->sample_rate = 48000;
4220 ret_error = true;
4221 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4222 in->config.format = PCM_FORMAT_S24_3LE;
4223 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4224 in->config.format = PCM_FORMAT_S24_LE;
4225 } else {
4226 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4227 ret_error = true;
4228 }
4229
4230 if (ret_error) {
4231 ret = -EINVAL;
4232 goto err_open;
4233 }
4234 }
4235
4236 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004237 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004238 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004239 buffer_size = get_input_buffer_size(config->sample_rate,
4240 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004241 channel_count,
4242 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004243 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004244 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4245 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4246 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004247 (in->config.rate == 8000 || in->config.rate == 16000 ||
4248 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004249 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4250 voice_extn_compress_voip_open_input_stream(in);
4251 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004252 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004254 /* This stream could be for sound trigger lab,
4255 get sound trigger pcm if present */
4256 audio_extn_sound_trigger_check_and_get_session(in);
4257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004259 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004260 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261
4262err_open:
4263 free(in);
4264 *stream_in = NULL;
4265 return ret;
4266}
4267
4268static void adev_close_input_stream(struct audio_hw_device *dev,
4269 struct audio_stream_in *stream)
4270{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004271 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004272 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004273 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304274
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304275 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004276
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304277 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004278 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304279
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004280 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304281 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004282 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304283 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004284 if (ret != 0)
4285 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4286 __func__, ret);
4287 } else
4288 in_standby(&stream->common);
4289
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004290 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004291 audio_extn_ssr_deinit();
4292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293
Mingming Yine62d7842013-10-25 16:26:03 -07004294 if(audio_extn_compr_cap_enabled() &&
4295 audio_extn_compr_cap_format_supported(in->config.format))
4296 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004297
Mingming Yinfd7607b2016-01-22 12:48:44 -08004298 if (in->is_st_session) {
4299 ALOGV("%s: sound trigger pcm stop lab", __func__);
4300 audio_extn_sound_trigger_stop_lab(in);
4301 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004302 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 return;
4304}
4305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004306static int adev_dump(const audio_hw_device_t *device __unused,
4307 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308{
4309 return 0;
4310}
4311
4312static int adev_close(hw_device_t *device)
4313{
4314 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004315
4316 if (!adev)
4317 return 0;
4318
4319 pthread_mutex_lock(&adev_init_lock);
4320
4321 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004322 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004323 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004324 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004325 audio_route_free(adev->audio_route);
4326 free(adev->snd_dev_ref_cnt);
4327 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004328 if (adev->adm_deinit)
4329 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004330 free(device);
4331 adev = NULL;
4332 }
4333 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 return 0;
4336}
4337
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004338/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4339 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4340 * just that it _might_ work.
4341 */
4342static int period_size_is_plausible_for_low_latency(int period_size)
4343{
4344 switch (period_size) {
4345 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004346 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004347 case 240:
4348 case 320:
4349 case 480:
4350 return 1;
4351 default:
4352 return 0;
4353 }
4354}
4355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356static int adev_open(const hw_module_t *module, const char *name,
4357 hw_device_t **device)
4358{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004359 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4361
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004362 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004363 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004364 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004365 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004366 ALOGD("%s: returning existing instance of adev", __func__);
4367 ALOGD("%s: exit", __func__);
4368 pthread_mutex_unlock(&adev_init_lock);
4369 return 0;
4370 }
4371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372 adev = calloc(1, sizeof(struct audio_device));
4373
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004374 if (!adev) {
4375 pthread_mutex_unlock(&adev_init_lock);
4376 return -ENOMEM;
4377 }
4378
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004379 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4382 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4383 adev->device.common.module = (struct hw_module_t *)module;
4384 adev->device.common.close = adev_close;
4385
4386 adev->device.init_check = adev_init_check;
4387 adev->device.set_voice_volume = adev_set_voice_volume;
4388 adev->device.set_master_volume = adev_set_master_volume;
4389 adev->device.get_master_volume = adev_get_master_volume;
4390 adev->device.set_master_mute = adev_set_master_mute;
4391 adev->device.get_master_mute = adev_get_master_mute;
4392 adev->device.set_mode = adev_set_mode;
4393 adev->device.set_mic_mute = adev_set_mic_mute;
4394 adev->device.get_mic_mute = adev_get_mic_mute;
4395 adev->device.set_parameters = adev_set_parameters;
4396 adev->device.get_parameters = adev_get_parameters;
4397 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4398 adev->device.open_output_stream = adev_open_output_stream;
4399 adev->device.close_output_stream = adev_close_output_stream;
4400 adev->device.open_input_stream = adev_open_input_stream;
4401 adev->device.close_input_stream = adev_close_input_stream;
4402 adev->device.dump = adev_dump;
4403
4404 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004406 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004407 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004410 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004411 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004412 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004413 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004414 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004415 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004416 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004417 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304418 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304419 adev->perf_lock_opts[0] = 0x101;
4420 adev->perf_lock_opts[1] = 0x20E;
4421 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304422
4423 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4424 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004426 adev->platform = platform_init(adev);
4427 if (!adev->platform) {
4428 free(adev->snd_dev_ref_cnt);
4429 free(adev);
4430 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4431 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004432 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004433 return -EINVAL;
4434 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004435
Naresh Tanniru4c630392014-05-12 01:05:52 +05304436 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4437
Eric Laurentc4aef752013-09-12 17:45:53 -07004438 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4439 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4440 if (adev->visualizer_lib == NULL) {
4441 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4442 } else {
4443 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4444 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004445 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004446 "visualizer_hal_start_output");
4447 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004448 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004449 "visualizer_hal_stop_output");
4450 }
4451 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004452 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004453 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004454
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004455 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4456 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4457 if (adev->offload_effects_lib == NULL) {
4458 ALOGE("%s: DLOPEN failed for %s", __func__,
4459 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4460 } else {
4461 ALOGV("%s: DLOPEN successful for %s", __func__,
4462 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4463 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304464 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004465 "offload_effects_bundle_hal_start_output");
4466 adev->offload_effects_stop_output =
4467 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4468 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004469 adev->offload_effects_set_hpx_state =
4470 (int (*)(bool))dlsym(adev->offload_effects_lib,
4471 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304472 adev->offload_effects_get_parameters =
4473 (void (*)(struct str_parms *, struct str_parms *))
4474 dlsym(adev->offload_effects_lib,
4475 "offload_effects_bundle_get_parameters");
4476 adev->offload_effects_set_parameters =
4477 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4478 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004479 }
4480 }
4481
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004482 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4483 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4484 if (adev->adm_lib == NULL) {
4485 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4486 } else {
4487 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4488 adev->adm_init = (adm_init_t)
4489 dlsym(adev->adm_lib, "adm_init");
4490 adev->adm_deinit = (adm_deinit_t)
4491 dlsym(adev->adm_lib, "adm_deinit");
4492 adev->adm_register_input_stream = (adm_register_input_stream_t)
4493 dlsym(adev->adm_lib, "adm_register_input_stream");
4494 adev->adm_register_output_stream = (adm_register_output_stream_t)
4495 dlsym(adev->adm_lib, "adm_register_output_stream");
4496 adev->adm_deregister_stream = (adm_deregister_stream_t)
4497 dlsym(adev->adm_lib, "adm_deregister_stream");
4498 adev->adm_request_focus = (adm_request_focus_t)
4499 dlsym(adev->adm_lib, "adm_request_focus");
4500 adev->adm_abandon_focus = (adm_abandon_focus_t)
4501 dlsym(adev->adm_lib, "adm_abandon_focus");
4502 }
4503 }
4504
Mingming Yin514a8bc2014-07-29 15:22:21 -07004505 adev->bt_wb_speech_enabled = false;
4506
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004507 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508 *device = &adev->device.common;
4509
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004510 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4511 &adev->streams_output_cfg_list);
4512
Kiran Kandi910e1862013-10-29 13:29:42 -07004513 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004514
4515 char value[PROPERTY_VALUE_MAX];
4516 int trial;
4517 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4518 trial = atoi(value);
4519 if (period_size_is_plausible_for_low_latency(trial)) {
4520 pcm_config_low_latency.period_size = trial;
4521 pcm_config_low_latency.start_threshold = trial / 4;
4522 pcm_config_low_latency.avail_min = trial / 4;
4523 configured_low_latency_capture_period_size = trial;
4524 }
4525 }
4526 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4527 trial = atoi(value);
4528 if (period_size_is_plausible_for_low_latency(trial)) {
4529 configured_low_latency_capture_period_size = trial;
4530 }
4531 }
4532
vivek mehta446c3962015-09-14 10:57:35 -07004533 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004534 pthread_mutex_unlock(&adev_init_lock);
4535
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004536 if (adev->adm_init)
4537 adev->adm_data = adev->adm_init();
4538
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304539 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004540 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 return 0;
4542}
4543
4544static struct hw_module_methods_t hal_module_methods = {
4545 .open = adev_open,
4546};
4547
4548struct audio_module HAL_MODULE_INFO_SYM = {
4549 .common = {
4550 .tag = HARDWARE_MODULE_TAG,
4551 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4552 .hal_api_version = HARDWARE_HAL_API_VERSION,
4553 .id = AUDIO_HARDWARE_MODULE_ID,
4554 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004555 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 .methods = &hal_module_methods,
4557 },
4558};