blob: d6e81b239facb1d2bf0b5be4b1ba189c7f2e08a0 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053077/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
78#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080080#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070081#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
82
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070083#define PROXY_OPEN_RETRY_COUNT 100
84#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080085
Mingming Yin08c7e312015-03-16 18:10:58 -070086#ifdef USE_LL_AS_PRIMARY_OUTPUT
87#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
88#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
89#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080090#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070091#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
92#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080093
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070094static unsigned int configured_low_latency_capture_period_size =
95 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
96
Eric Laurentb23d5282013-05-14 15:27:20 -070097struct pcm_config pcm_config_deep_buffer = {
98 .channels = 2,
99 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
100 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
101 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
102 .format = PCM_FORMAT_S16_LE,
103 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104 .stop_threshold = INT_MAX,
105 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
106};
107
108struct pcm_config pcm_config_low_latency = {
109 .channels = 2,
110 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
111 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
112 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
113 .format = PCM_FORMAT_S16_LE,
114 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115 .stop_threshold = INT_MAX,
116 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
117};
118
119struct pcm_config pcm_config_hdmi_multi = {
120 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
122 .period_size = HDMI_MULTI_PERIOD_SIZE,
123 .period_count = HDMI_MULTI_PERIOD_COUNT,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = 0,
126 .stop_threshold = INT_MAX,
127 .avail_min = 0,
128};
129
130struct pcm_config pcm_config_audio_capture = {
131 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700132 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
133 .format = PCM_FORMAT_S16_LE,
134};
135
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700136#define AFE_PROXY_CHANNEL_COUNT 2
137#define AFE_PROXY_SAMPLING_RATE 48000
138
139#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
140#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
141
142struct pcm_config pcm_config_afe_proxy_playback = {
143 .channels = AFE_PROXY_CHANNEL_COUNT,
144 .rate = AFE_PROXY_SAMPLING_RATE,
145 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
146 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
147 .format = PCM_FORMAT_S16_LE,
148 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149 .stop_threshold = INT_MAX,
150 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
151};
152
153#define AFE_PROXY_RECORD_PERIOD_SIZE 768
154#define AFE_PROXY_RECORD_PERIOD_COUNT 4
155
156struct pcm_config pcm_config_afe_proxy_record = {
157 .channels = AFE_PROXY_CHANNEL_COUNT,
158 .rate = AFE_PROXY_SAMPLING_RATE,
159 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
160 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
163 .stop_threshold = INT_MAX,
164 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
165};
166
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800167const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700168 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
169 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700170 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
171 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700173 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700174 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
180 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
181 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700184 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700186 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700187 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800188 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800189 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700191
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700192 [USECASE_VOICE2_CALL] = "voice2-call",
193 [USECASE_VOLTE_CALL] = "volte-call",
194 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800195 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800196 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
197 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800198 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700199 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
200 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800202 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
203 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
204 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
205
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700206 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
207 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700208 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
209 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700210
211 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
212 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700213};
214
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215static const audio_usecase_t offload_usecases[] = {
216 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700217 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700225};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226
227#define STRING_TO_ENUM(string) { #string, string }
228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229struct string_to_enum {
230 const char *name;
231 uint32_t value;
232};
233
234static const struct string_to_enum out_channels_name_to_enum_table[] = {
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
243};
244
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700245static const struct string_to_enum out_formats_name_to_enum_table[] = {
246 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
247 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
248 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800249 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
250 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
251};
252
253//list of all supported sample rates by HDMI specification.
254static const int out_hdmi_sample_rates[] = {
255 32000, 44100, 48000, 88200, 96000, 176400, 192000,
256};
257
258static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
259 STRING_TO_ENUM(32000),
260 STRING_TO_ENUM(44100),
261 STRING_TO_ENUM(48000),
262 STRING_TO_ENUM(88200),
263 STRING_TO_ENUM(96000),
264 STRING_TO_ENUM(176400),
265 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700266};
267
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700268static struct audio_device *adev = NULL;
269static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700270static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700271//cache last MBDRC cal step level
272static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700273
vivek mehtaa76401a2015-04-24 14:12:15 -0700274__attribute__ ((visibility ("default")))
275bool audio_hw_send_gain_dep_calibration(int level) {
276 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700277 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700278
279 pthread_mutex_lock(&adev_init_lock);
280
281 if (adev != NULL && adev->platform != NULL) {
282 pthread_mutex_lock(&adev->lock);
283 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700284
285 // if cal set fails, cache level info
286 // if cal set succeds, reset known last cal set
287 if (!ret_val)
288 last_known_cal_step = level;
289 else if (last_known_cal_step != -1)
290 last_known_cal_step = -1;
291
vivek mehtaa76401a2015-04-24 14:12:15 -0700292 pthread_mutex_unlock(&adev->lock);
293 } else {
294 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
295 }
296
297 pthread_mutex_unlock(&adev_init_lock);
298
299 return ret_val;
300}
301
Ashish Jain5106d362016-05-11 19:23:33 +0530302static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
303{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800304 bool gapless_enabled = false;
305 const char *mixer_ctl_name = "Compress Gapless Playback";
306 struct mixer_ctl *ctl;
307
308 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530309 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
310
311 /*Disable gapless if its AV playback*/
312 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800313
314 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
315 if (!ctl) {
316 ALOGE("%s: Could not get ctl for mixer cmd - %s",
317 __func__, mixer_ctl_name);
318 return -EINVAL;
319 }
320
321 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
322 ALOGE("%s: Could not set gapless mode %d",
323 __func__, gapless_enabled);
324 return -EINVAL;
325 }
326 return 0;
327}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700328
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329static bool is_supported_format(audio_format_t format)
330{
Eric Laurent86e17132013-09-12 17:49:30 -0700331 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530332 format == AUDIO_FORMAT_AAC_LC ||
333 format == AUDIO_FORMAT_AAC_HE_V1 ||
334 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 format == AUDIO_FORMAT_AAC_ADTS_LC ||
336 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
337 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530338 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
339 format == AUDIO_FORMAT_PCM_8_24_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700340 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530341 format == AUDIO_FORMAT_AC3 ||
342 format == AUDIO_FORMAT_E_AC3 ||
343 format == AUDIO_FORMAT_DTS ||
344 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800345 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530346 format == AUDIO_FORMAT_ALAC ||
347 format == AUDIO_FORMAT_APE ||
348 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800349 format == AUDIO_FORMAT_WMA ||
350 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800351 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700352
353 return false;
354}
355
356static int get_snd_codec_id(audio_format_t format)
357{
358 int id = 0;
359
Ashish Jainf9b78162014-08-25 20:36:25 +0530360 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700361 case AUDIO_FORMAT_MP3:
362 id = SND_AUDIOCODEC_MP3;
363 break;
364 case AUDIO_FORMAT_AAC:
365 id = SND_AUDIOCODEC_AAC;
366 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530367 case AUDIO_FORMAT_AAC_ADTS:
368 id = SND_AUDIOCODEC_AAC;
369 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700370 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800371 id = SND_AUDIOCODEC_PCM;
372 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700373 case AUDIO_FORMAT_FLAC:
374 id = SND_AUDIOCODEC_FLAC;
375 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530376 case AUDIO_FORMAT_ALAC:
377 id = SND_AUDIOCODEC_ALAC;
378 break;
379 case AUDIO_FORMAT_APE:
380 id = SND_AUDIOCODEC_APE;
381 break;
382 case AUDIO_FORMAT_VORBIS:
383 id = SND_AUDIOCODEC_VORBIS;
384 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800385 case AUDIO_FORMAT_WMA:
386 id = SND_AUDIOCODEC_WMA;
387 break;
388 case AUDIO_FORMAT_WMA_PRO:
389 id = SND_AUDIOCODEC_WMA_PRO;
390 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530391 case AUDIO_FORMAT_AC3:
392 id = SND_AUDIOCODEC_AC3;
393 break;
394 case AUDIO_FORMAT_E_AC3:
395 case AUDIO_FORMAT_E_AC3_JOC:
396 id = SND_AUDIOCODEC_EAC3;
397 break;
398 case AUDIO_FORMAT_DTS:
399 case AUDIO_FORMAT_DTS_HD:
400 id = SND_AUDIOCODEC_DTS;
401 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700402 default:
Mingming Yin90310102013-11-13 16:57:00 -0800403 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700404 }
405
406 return id;
407}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800408
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530409int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530410{
411 int snd_scard_state;
412
413 if (!adev)
414 return SND_CARD_STATE_OFFLINE;
415
416 pthread_mutex_lock(&adev->snd_card_status.lock);
417 snd_scard_state = adev->snd_card_status.state;
418 pthread_mutex_unlock(&adev->snd_card_status.lock);
419
420 return snd_scard_state;
421}
422
423static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
424{
425 if (!adev)
426 return -ENOSYS;
427
428 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700429 if (adev->snd_card_status.state != snd_scard_state) {
430 adev->snd_card_status.state = snd_scard_state;
431 platform_snd_card_update(adev->platform, snd_scard_state);
432 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530433 pthread_mutex_unlock(&adev->snd_card_status.lock);
434
435 return 0;
436}
437
Avinash Vaish71a8b972014-07-24 15:36:33 +0530438static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
439 struct audio_usecase *uc_info)
440{
441 struct listnode *node;
442 struct audio_usecase *usecase;
443
444 if (uc_info == NULL)
445 return -EINVAL;
446
447 /* Re-route all voice usecases on the shared backend other than the
448 specified usecase to new snd devices */
449 list_for_each(node, &adev->usecase_list) {
450 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800451 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530452 enable_audio_route(adev, usecase);
453 }
454 return 0;
455}
456
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700457int pcm_ioctl(struct pcm *pcm, int request, ...)
458{
459 va_list ap;
460 void * arg;
461 int pcm_fd = *(int*)pcm;
462
463 va_start(ap, request);
464 arg = va_arg(ap, void *);
465 va_end(ap);
466
467 return ioctl(pcm_fd, request, arg);
468}
469
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700470int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700471 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800472{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700473 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700474 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800475
476 if (usecase == NULL)
477 return -EINVAL;
478
479 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
480
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800481 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700482 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800483 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700484 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800485
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800486#ifdef DS1_DOLBY_DAP_ENABLED
487 audio_extn_dolby_set_dmid(adev);
488 audio_extn_dolby_set_endpoint(adev);
489#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700490 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700491 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530492 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700493 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530494 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800495 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700496 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700497 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700498 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800499 ALOGV("%s: exit", __func__);
500 return 0;
501}
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700504 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800505{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700506 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700507 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800508
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530509 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800510 return -EINVAL;
511
512 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513 if (usecase->type == PCM_CAPTURE)
514 snd_device = usecase->in_snd_device;
515 else
516 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800517 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700518 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700519 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700521 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530522 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 ALOGV("%s: exit", __func__);
524 return 0;
525}
526
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700527int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700528 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800529{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530530 int i, num_devices = 0;
531 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700532 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
533
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 if (snd_device < SND_DEVICE_MIN ||
535 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800536 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800537 return -EINVAL;
538 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700539
540 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700541
542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700546 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700547 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700548 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700549 return 0;
550 }
551
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530552
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700553 if (audio_extn_spkr_prot_is_enabled())
554 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700555
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700556
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800557 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
558 audio_extn_spkr_prot_is_enabled()) {
559 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700560 adev->snd_dev_ref_cnt[snd_device]--;
561 return -EINVAL;
562 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200563 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800564 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800565 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200566 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800567 return -EINVAL;
568 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530569 } else if (platform_can_split_snd_device(adev->platform, snd_device,
570 &num_devices, new_snd_devices)) {
571 for (i = 0; i < num_devices; i++) {
572 enable_snd_device(adev, new_snd_devices[i]);
573 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800574 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700575 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700576 /* due to the possibility of calibration overwrite between listen
577 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700578 audio_extn_sound_trigger_update_device_status(snd_device,
579 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530580 audio_extn_listen_update_device_status(snd_device,
581 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700582 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700583 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700584 audio_extn_sound_trigger_update_device_status(snd_device,
585 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530586 audio_extn_listen_update_device_status(snd_device,
587 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700588 return -EINVAL;
589 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300590 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700591 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530592
593 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
594 !adev->native_playback_enabled &&
595 audio_is_true_native_stream_active(adev)) {
596 ALOGD("%s: %d: napb: enabling native mode in hardware",
597 __func__, __LINE__);
598 audio_route_apply_and_update_path(adev->audio_route,
599 "true-native-mode");
600 adev->native_playback_enabled = true;
601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 return 0;
604}
605
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700606int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700607 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800608{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530609 int i, num_devices = 0;
610 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700611 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
612
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800613 if (snd_device < SND_DEVICE_MIN ||
614 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800615 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800616 return -EINVAL;
617 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
619 ALOGE("%s: device ref cnt is already 0", __func__);
620 return -EINVAL;
621 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700622
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700624
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700625 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
626 ALOGE("%s: Invalid sound device returned", __func__);
627 return -EINVAL;
628 }
629
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700631 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800632 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
633 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700634 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530635 } else if (platform_can_split_snd_device(adev->platform, snd_device,
636 &num_devices, new_snd_devices)) {
637 for (i = 0; i < num_devices; i++) {
638 disable_snd_device(adev, new_snd_devices[i]);
639 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300640 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700641 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300642 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700643
Ashish Jain81eb2a82015-05-13 10:52:34 +0530644 if (snd_device == SND_DEVICE_OUT_HDMI)
645 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530646 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
647 adev->native_playback_enabled) {
648 ALOGD("%s: %d: napb: disabling native mode in hardware",
649 __func__, __LINE__);
650 audio_route_reset_and_update_path(adev->audio_route,
651 "true-native-mode");
652 adev->native_playback_enabled = false;
653 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530654
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200655 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700656 audio_extn_sound_trigger_update_device_status(snd_device,
657 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530658 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800659 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662 return 0;
663}
664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530666 struct audio_usecase *uc_info,
667 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668{
669 struct listnode *node;
670 struct audio_usecase *usecase;
671 bool switch_device[AUDIO_USECASE_MAX];
672 int i, num_uc_to_switch = 0;
673
674 /*
675 * This function is to make sure that all the usecases that are active on
676 * the hardware codec backend are always routed to any one device that is
677 * handled by the hardware codec.
678 * For example, if low-latency and deep-buffer usecases are currently active
679 * on speaker and out_set_parameters(headset) is received on low-latency
680 * output, then we have to make sure deep-buffer is also switched to headset,
681 * because of the limitation that both the devices cannot be enabled
682 * at the same time as they share the same backend.
683 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700684 /*
685 * This call is to check if we need to force routing for a particular stream
686 * If there is a backend configuration change for the device when a
687 * new stream starts, then ADM needs to be closed and re-opened with the new
688 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800689 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700690 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800691 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
692 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530693
694 ALOGD("%s:becf: force routing %d", __func__, force_routing);
695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800697 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800698 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 for (i = 0; i < AUDIO_USECASE_MAX; i++)
700 switch_device[i] = false;
701
702 list_for_each(node, &adev->usecase_list) {
703 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800704
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530705 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
706 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530707 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530708 platform_get_snd_device_name(usecase->out_snd_device),
709 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800710 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530711 usecase != uc_info &&
712 (usecase->out_snd_device != snd_device || force_routing) &&
713 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
714 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
715 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
716 __func__, use_case_table[usecase->id],
717 platform_get_snd_device_name(usecase->out_snd_device));
718 disable_audio_route(adev, usecase);
719 switch_device[usecase->id] = true;
720 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
722 }
723
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530724 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
725 num_uc_to_switch);
726
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700727 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700728 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530730 /* Make sure the previous devices to be disabled first and then enable the
731 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700732 list_for_each(node, &adev->usecase_list) {
733 usecase = node_to_item(node, struct audio_usecase, list);
734 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700735 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 }
737 }
738
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700739 list_for_each(node, &adev->usecase_list) {
740 usecase = node_to_item(node, struct audio_usecase, list);
741 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700742 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700743 }
744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 /* Re-route all the usecases on the shared backend other than the
747 specified usecase to new snd devices */
748 list_for_each(node, &adev->usecase_list) {
749 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530750 /* Update the out_snd_device only before enabling the audio route */
751 if (switch_device[usecase->id]) {
752 usecase->out_snd_device = snd_device;
753 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530754 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530755 use_case_table[usecase->id],
756 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530757 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530758 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 }
760 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 }
762}
763
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530764static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700765 struct audio_usecase *uc_info,
766 snd_device_t snd_device)
767{
768 struct listnode *node;
769 struct audio_usecase *usecase;
770 bool switch_device[AUDIO_USECASE_MAX];
771 int i, num_uc_to_switch = 0;
772
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530773 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
774 snd_device);
775 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 /*
777 * This function is to make sure that all the active capture usecases
778 * are always routed to the same input sound device.
779 * For example, if audio-record and voice-call usecases are currently
780 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
781 * is received for voice call then we have to make sure that audio-record
782 * usecase is also switched to earpiece i.e. voice-dmic-ef,
783 * because of the limitation that two devices cannot be enabled
784 * at the same time if they share the same backend.
785 */
786 for (i = 0; i < AUDIO_USECASE_MAX; i++)
787 switch_device[i] = false;
788
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800791 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700792 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530793 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700794 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530795 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
796 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700797 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700798 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
799 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700800 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700801 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700802 switch_device[usecase->id] = true;
803 num_uc_to_switch++;
804 }
805 }
806
807 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700808 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700809
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530810 /* Make sure the previous devices to be disabled first and then enable the
811 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700812 list_for_each(node, &adev->usecase_list) {
813 usecase = node_to_item(node, struct audio_usecase, list);
814 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700815 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800816 }
817 }
818
819 list_for_each(node, &adev->usecase_list) {
820 usecase = node_to_item(node, struct audio_usecase, list);
821 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700822 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700823 }
824 }
825
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700826 /* Re-route all the usecases on the shared backend other than the
827 specified usecase to new snd devices */
828 list_for_each(node, &adev->usecase_list) {
829 usecase = node_to_item(node, struct audio_usecase, list);
830 /* Update the in_snd_device only before enabling the audio route */
831 if (switch_device[usecase->id] ) {
832 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800833 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530834 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700835 }
836 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700837 }
838}
839
Mingming Yin3a941d42016-02-17 18:08:05 -0800840static void reset_hdmi_sink_caps(struct stream_out *out) {
841 int i = 0;
842
843 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
844 out->supported_channel_masks[i] = 0;
845 }
846 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
847 out->supported_formats[i] = 0;
848 }
849 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
850 out->supported_sample_rates[i] = 0;
851 }
852}
853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800855static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800856{
Mingming Yin3a941d42016-02-17 18:08:05 -0800857 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700858 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800859
Mingming Yin3a941d42016-02-17 18:08:05 -0800860 reset_hdmi_sink_caps(out);
861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800864 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700865 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800866 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
867 case 6:
868 ALOGV("%s: HDMI supports 5.1 channels", __func__);
869 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
870 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
871 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
872 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
873 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874 break;
875 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800876 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700877 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 break;
879 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800880
881 // check channel format caps
882 i = 0;
883 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
884 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
885 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
886 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
887 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
888 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
889 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
890 }
891
892 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
893 ALOGV(":%s HDMI supports DTS format", __func__);
894 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
895 }
896
897 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
898 ALOGV(":%s HDMI supports DTS HD format", __func__);
899 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
900 }
901
902
903 // check sample rate caps
904 i = 0;
905 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
906 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
907 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
908 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
909 }
910 }
911
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700912 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913}
914
Alexy Josephb1379942016-01-29 15:49:38 -0800915audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800916 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700917{
918 struct audio_usecase *usecase;
919 struct listnode *node;
920
921 list_for_each(node, &adev->usecase_list) {
922 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800923 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700924 ALOGV("%s: usecase id %d", __func__, usecase->id);
925 return usecase->id;
926 }
927 }
928 return USECASE_INVALID;
929}
930
Alexy Josephb1379942016-01-29 15:49:38 -0800931struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700932 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933{
934 struct audio_usecase *usecase;
935 struct listnode *node;
936
937 list_for_each(node, &adev->usecase_list) {
938 usecase = node_to_item(node, struct audio_usecase, list);
939 if (usecase->id == uc_id)
940 return usecase;
941 }
942 return NULL;
943}
944
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530945/*
946 * is a true native playback active
947 */
948bool audio_is_true_native_stream_active(struct audio_device *adev)
949{
950 bool active = false;
951 int i = 0;
952 struct listnode *node;
953
954 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
955 ALOGV("%s:napb: not in true mode or non hdphones device",
956 __func__);
957 active = false;
958 goto exit;
959 }
960
961 list_for_each(node, &adev->usecase_list) {
962 struct audio_usecase *uc;
963 uc = node_to_item(node, struct audio_usecase, list);
964 struct stream_out *curr_out =
965 (struct stream_out*) uc->stream.out;
966
967 if (curr_out && PCM_PLAYBACK == uc->type) {
968 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
969 "(%d) device %s", __func__, i++, use_case_table[uc->id],
970 uc->id, curr_out->sample_rate,
971 curr_out->bit_width,
972 platform_get_snd_device_name(uc->out_snd_device));
973
974 if (is_offload_usecase(uc->id) &&
975 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
976 active = true;
977 ALOGD("%s:napb:native stream detected", __func__);
978 }
979 }
980 }
981exit:
982 return active;
983}
984
985
986static bool force_device_switch(struct audio_usecase *usecase)
987{
988 bool ret = false;
989 bool is_it_true_mode = false;
990
991 if (is_offload_usecase(usecase->id) &&
992 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800993 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
994 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
995 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530996 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
997 if ((is_it_true_mode && !adev->native_playback_enabled) ||
998 (!is_it_true_mode && adev->native_playback_enabled)){
999 ret = true;
1000 ALOGD("napb: time to toggle native mode");
1001 }
1002 }
1003
1004 return ret;
1005}
1006
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001007int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001009 snd_device_t out_snd_device = SND_DEVICE_NONE;
1010 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011 struct audio_usecase *usecase = NULL;
1012 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001013 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001014 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001015 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301018 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1019
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 usecase = get_usecase_from_list(adev, uc_id);
1021 if (usecase == NULL) {
1022 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1023 return -EINVAL;
1024 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001026 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001027 (usecase->type == VOIP_CALL) ||
1028 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001029 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001030 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 usecase->devices = usecase->stream.out->devices;
1033 } else {
1034 /*
1035 * If the voice call is active, use the sound devices of voice call usecase
1036 * so that it would not result any device switch. All the usecases will
1037 * be switched to new device when select_devices() is called for voice call
1038 * usecase. This is to avoid switching devices for voice call when
1039 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001040 * choose voice call device only if the use case device is
1041 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001043 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001044 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001045 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001046 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1047 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1048 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 in_snd_device = vc_usecase->in_snd_device;
1050 out_snd_device = vc_usecase->out_snd_device;
1051 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001052 } else if (voice_extn_compress_voip_is_active(adev)) {
1053 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001054 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301055 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001056 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001057 in_snd_device = voip_usecase->in_snd_device;
1058 out_snd_device = voip_usecase->out_snd_device;
1059 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001060 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001061 hfp_ucid = audio_extn_hfp_get_usecase();
1062 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001063 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001064 in_snd_device = hfp_usecase->in_snd_device;
1065 out_snd_device = hfp_usecase->out_snd_device;
1066 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067 }
1068 if (usecase->type == PCM_PLAYBACK) {
1069 usecase->devices = usecase->stream.out->devices;
1070 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001071 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001072 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001073 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001074 if (usecase->stream.out == adev->primary_output &&
1075 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001076 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001077 select_devices(adev, adev->active_input->usecase);
1078 }
1079 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 } else if (usecase->type == PCM_CAPTURE) {
1081 usecase->devices = usecase->stream.in->device;
1082 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001083 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001084 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001085 if (adev->active_input &&
1086 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301087 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1088 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1089 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001090 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001091 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001092 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1093 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001094 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001095 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001096 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097 }
1098 }
1099
1100 if (out_snd_device == usecase->out_snd_device &&
1101 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301102
1103 if (!force_device_switch(usecase))
1104 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 }
1106
sangwoobc677242013-08-08 16:53:43 +09001107 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001108 out_snd_device, platform_get_snd_device_name(out_snd_device),
1109 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 /*
1112 * Limitation: While in call, to do a device switch we need to disable
1113 * and enable both RX and TX devices though one of them is same as current
1114 * device.
1115 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001116 if ((usecase->type == VOICE_CALL) &&
1117 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1118 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001119 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001120 }
1121
1122 if (((usecase->type == VOICE_CALL) ||
1123 (usecase->type == VOIP_CALL)) &&
1124 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1125 /* Disable sidetone only if voice/voip call already exists */
1126 if (voice_is_call_state_active(adev) ||
1127 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001128 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001129 }
1130
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 /* Disable current sound devices */
1132 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001133 disable_audio_route(adev, usecase);
1134 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001135 }
1136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001138 disable_audio_route(adev, usecase);
1139 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001140 }
1141
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001142 /* Applicable only on the targets that has external modem.
1143 * New device information should be sent to modem before enabling
1144 * the devices to reduce in-call device switch time.
1145 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001146 if ((usecase->type == VOICE_CALL) &&
1147 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1148 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001149 status = platform_switch_voice_call_enable_device_config(adev->platform,
1150 out_snd_device,
1151 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001152 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001153
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 /* Enable new sound devices */
1155 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001156 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001157 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158 }
1159
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001160 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301161 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001162 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001163 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164
Avinash Vaish71a8b972014-07-24 15:36:33 +05301165 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001166 status = platform_switch_voice_call_device_post(adev->platform,
1167 out_snd_device,
1168 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301169 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001170 /* Enable sidetone only if voice/voip call already exists */
1171 if (voice_is_call_state_active(adev) ||
1172 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001173 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301174 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001175
sangwoo170731f2013-06-08 15:36:36 +09001176 usecase->in_snd_device = in_snd_device;
1177 usecase->out_snd_device = out_snd_device;
1178
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301179 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001180 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301181 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001182 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301183 usecase->stream.out->flags,
1184 usecase->stream.out->format,
1185 usecase->stream.out->sample_rate,
1186 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301187 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301188 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001189 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301190 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001191
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001192 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001193
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001194 /* Applicable only on the targets that has external modem.
1195 * Enable device command should be sent to modem only after
1196 * enabling voice call mixer controls
1197 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001198 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001199 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1200 out_snd_device,
1201 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301202 ALOGD("%s: done",__func__);
1203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 return status;
1205}
1206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207static int stop_input_stream(struct stream_in *in)
1208{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301209 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001210 struct audio_usecase *uc_info;
1211 struct audio_device *adev = in->dev;
1212
Eric Laurentc8400632013-02-14 19:04:54 -08001213 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214
Eric Laurent994a6932013-07-17 11:51:42 -07001215 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001216 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217 uc_info = get_usecase_from_list(adev, in->usecase);
1218 if (uc_info == NULL) {
1219 ALOGE("%s: Could not find the usecase (%d) in the list",
1220 __func__, in->usecase);
1221 return -EINVAL;
1222 }
1223
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001224 /* Close in-call recording streams */
1225 voice_check_and_stop_incall_rec_usecase(adev, in);
1226
Eric Laurent150dbfe2013-02-27 14:31:02 -08001227 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001228 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001229
1230 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001231 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001233 list_remove(&uc_info->list);
1234 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235
Eric Laurent994a6932013-07-17 11:51:42 -07001236 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237 return ret;
1238}
1239
1240int start_input_stream(struct stream_in *in)
1241{
1242 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001243 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244 struct audio_usecase *uc_info;
1245 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301246 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247
Mingming Yin2664a5b2015-09-03 10:53:11 -07001248 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1249 if (get_usecase_from_list(adev, usecase) == NULL)
1250 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301251 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1252 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001253
Naresh Tanniru80659832014-06-04 18:17:56 +05301254
1255 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301256 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301257 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301258 goto error_config;
1259 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301260
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001261 /* Check if source matches incall recording usecase criteria */
1262 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1263 if (ret)
1264 goto error_config;
1265 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001266 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1267
1268 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1269 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1270 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001271 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001272 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001273
Eric Laurentb23d5282013-05-14 15:27:20 -07001274 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 if (in->pcm_device_id < 0) {
1276 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1277 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001278 ret = -EINVAL;
1279 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281
1282 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001283 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001284
1285 if (!uc_info) {
1286 ret = -ENOMEM;
1287 goto error_config;
1288 }
1289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 uc_info->id = in->usecase;
1291 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001292 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293 uc_info->devices = in->device;
1294 uc_info->in_snd_device = SND_DEVICE_NONE;
1295 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001297 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301298 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1299 adev->perf_lock_opts,
1300 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001301 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301303 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1304 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001305
1306 unsigned int flags = PCM_IN;
1307 unsigned int pcm_open_retry_count = 0;
1308
1309 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1310 flags |= PCM_MMAP | PCM_NOIRQ;
1311 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1312 }
1313
1314 while (1) {
1315 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1316 flags, &in->config);
1317 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1318 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1319 if (in->pcm != NULL) {
1320 pcm_close(in->pcm);
1321 in->pcm = NULL;
1322 }
1323 if (pcm_open_retry_count-- == 0) {
1324 ret = -EIO;
1325 goto error_open;
1326 }
1327 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1328 continue;
1329 }
1330 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001332
1333 ALOGV("%s: pcm_prepare", __func__);
1334 ret = pcm_prepare(in->pcm);
1335 if (ret < 0) {
1336 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1337 pcm_close(in->pcm);
1338 in->pcm = NULL;
1339 goto error_open;
1340 }
1341
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301342 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001343 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001344
Eric Laurentc8400632013-02-14 19:04:54 -08001345 return ret;
1346
1347error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301348 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001350error_config:
1351 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301352 /*
1353 * sleep 50ms to allow sufficient time for kernel
1354 * drivers to recover incases like SSR.
1355 */
1356 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001358
1359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001360}
1361
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001362void lock_input_stream(struct stream_in *in)
1363{
1364 pthread_mutex_lock(&in->pre_lock);
1365 pthread_mutex_lock(&in->lock);
1366 pthread_mutex_unlock(&in->pre_lock);
1367}
1368
1369void lock_output_stream(struct stream_out *out)
1370{
1371 pthread_mutex_lock(&out->pre_lock);
1372 pthread_mutex_lock(&out->lock);
1373 pthread_mutex_unlock(&out->pre_lock);
1374}
1375
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001376/* must be called with out->lock locked */
1377static int send_offload_cmd_l(struct stream_out* out, int command)
1378{
1379 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1380
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001381 if (!cmd) {
1382 ALOGE("failed to allocate mem for command 0x%x", command);
1383 return -ENOMEM;
1384 }
1385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001386 ALOGVV("%s %d", __func__, command);
1387
1388 cmd->cmd = command;
1389 list_add_tail(&out->offload_cmd_list, &cmd->node);
1390 pthread_cond_signal(&out->offload_cond);
1391 return 0;
1392}
1393
1394/* must be called iwth out->lock locked */
1395static void stop_compressed_output_l(struct stream_out *out)
1396{
1397 out->offload_state = OFFLOAD_STATE_IDLE;
1398 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001399 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001400 if (out->compr != NULL) {
1401 compress_stop(out->compr);
1402 while (out->offload_thread_blocked) {
1403 pthread_cond_wait(&out->cond, &out->lock);
1404 }
1405 }
1406}
1407
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001408bool is_offload_usecase(audio_usecase_t uc_id)
1409{
1410 unsigned int i;
1411 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1412 if (uc_id == offload_usecases[i])
1413 return true;
1414 }
1415 return false;
1416}
1417
vivek mehta446c3962015-09-14 10:57:35 -07001418static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001419{
vivek mehta446c3962015-09-14 10:57:35 -07001420 audio_usecase_t ret_uc = USECASE_INVALID;
1421 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001422 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001423 if (!adev->multi_offload_enable) {
1424 if (is_direct_pcm)
1425 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1426 else
1427 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001428
vivek mehta446c3962015-09-14 10:57:35 -07001429 pthread_mutex_lock(&adev->lock);
1430 if (get_usecase_from_list(adev, ret_uc) != NULL)
1431 ret_uc = USECASE_INVALID;
1432 pthread_mutex_unlock(&adev->lock);
1433
1434 return ret_uc;
1435 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001436
1437 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001438 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1439 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1440 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1441 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001442 break;
1443 }
1444 }
vivek mehta446c3962015-09-14 10:57:35 -07001445
1446 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1447 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001448}
1449
1450static void free_offload_usecase(struct audio_device *adev,
1451 audio_usecase_t uc_id)
1452{
vivek mehta446c3962015-09-14 10:57:35 -07001453 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001454 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001455
1456 if (!adev->multi_offload_enable)
1457 return;
1458
1459 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1460 if (offload_usecases[offload_uc_index] == uc_id) {
1461 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001462 break;
1463 }
1464 }
1465 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1466}
1467
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468static void *offload_thread_loop(void *context)
1469{
1470 struct stream_out *out = (struct stream_out *) context;
1471 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001472 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001474 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1475 set_sched_policy(0, SP_FOREGROUND);
1476 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1477
1478 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001479 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480 for (;;) {
1481 struct offload_cmd *cmd = NULL;
1482 stream_callback_event_t event;
1483 bool send_callback = false;
1484
1485 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1486 __func__, list_empty(&out->offload_cmd_list),
1487 out->offload_state);
1488 if (list_empty(&out->offload_cmd_list)) {
1489 ALOGV("%s SLEEPING", __func__);
1490 pthread_cond_wait(&out->offload_cond, &out->lock);
1491 ALOGV("%s RUNNING", __func__);
1492 continue;
1493 }
1494
1495 item = list_head(&out->offload_cmd_list);
1496 cmd = node_to_item(item, struct offload_cmd, node);
1497 list_remove(item);
1498
1499 ALOGVV("%s STATE %d CMD %d out->compr %p",
1500 __func__, out->offload_state, cmd->cmd, out->compr);
1501
1502 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1503 free(cmd);
1504 break;
1505 }
1506
1507 if (out->compr == NULL) {
1508 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001509 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001510 pthread_cond_signal(&out->cond);
1511 continue;
1512 }
1513 out->offload_thread_blocked = true;
1514 pthread_mutex_unlock(&out->lock);
1515 send_callback = false;
1516 switch(cmd->cmd) {
1517 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001518 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001519 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001520 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001521 send_callback = true;
1522 event = STREAM_CBK_EVENT_WRITE_READY;
1523 break;
1524 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001525 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301526 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001527 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301528 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001529 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301530 if (ret < 0)
1531 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301532 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301533 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001534 compress_drain(out->compr);
1535 else
1536 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301537 if (ret != -ENETRESET) {
1538 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301539 pthread_mutex_lock(&out->lock);
1540 out->send_new_metadata = 1;
1541 out->send_next_track_params = true;
1542 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301543 event = STREAM_CBK_EVENT_DRAIN_READY;
1544 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1545 } else
1546 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 break;
1548 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001549 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001550 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001551 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 send_callback = true;
1553 event = STREAM_CBK_EVENT_DRAIN_READY;
1554 break;
1555 default:
1556 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1557 break;
1558 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001559 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001560 out->offload_thread_blocked = false;
1561 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001562 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001563 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001564 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001565 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001566 free(cmd);
1567 }
1568
1569 pthread_cond_signal(&out->cond);
1570 while (!list_empty(&out->offload_cmd_list)) {
1571 item = list_head(&out->offload_cmd_list);
1572 list_remove(item);
1573 free(node_to_item(item, struct offload_cmd, node));
1574 }
1575 pthread_mutex_unlock(&out->lock);
1576
1577 return NULL;
1578}
1579
1580static int create_offload_callback_thread(struct stream_out *out)
1581{
1582 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1583 list_init(&out->offload_cmd_list);
1584 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1585 offload_thread_loop, out);
1586 return 0;
1587}
1588
1589static int destroy_offload_callback_thread(struct stream_out *out)
1590{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001591 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001592 stop_compressed_output_l(out);
1593 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1594
1595 pthread_mutex_unlock(&out->lock);
1596 pthread_join(out->offload_thread, (void **) NULL);
1597 pthread_cond_destroy(&out->offload_cond);
1598
1599 return 0;
1600}
1601
Mingming Yin21854652016-04-13 11:54:02 -07001602static bool allow_hdmi_channel_config(struct audio_device *adev,
1603 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001604{
1605 struct listnode *node;
1606 struct audio_usecase *usecase;
1607 bool ret = true;
1608
Mingming Yin21854652016-04-13 11:54:02 -07001609 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1610 ret = false;
1611 goto exit;
1612 }
1613
1614 if (audio_extn_passthru_is_active()) {
1615 ALOGI("%s: Compress audio passthrough is active,"
1616 "no HDMI config change allowed", __func__);
1617 ret = false;
1618 goto exit;
1619 }
1620
Eric Laurent07eeafd2013-10-06 12:52:49 -07001621 list_for_each(node, &adev->usecase_list) {
1622 usecase = node_to_item(node, struct audio_usecase, list);
1623 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1624 /*
1625 * If voice call is already existing, do not proceed further to avoid
1626 * disabling/enabling both RX and TX devices, CSD calls, etc.
1627 * Once the voice call done, the HDMI channels can be configured to
1628 * max channels of remaining use cases.
1629 */
1630 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001631 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001632 __func__);
1633 ret = false;
1634 break;
1635 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001636 if (!enable_passthru) {
1637 ALOGV("%s: multi channel playback is active, "
1638 "no change in HDMI channels", __func__);
1639 ret = false;
1640 break;
1641 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001642 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001643 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001644 if (!enable_passthru) {
1645 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1646 ", no change in HDMI channels", __func__,
1647 usecase->stream.out->channel_mask);
1648 ret = false;
1649 break;
1650 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001651 }
1652 }
1653 }
Mingming Yin21854652016-04-13 11:54:02 -07001654 ALOGV("allow hdmi config %d", ret);
1655exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656 return ret;
1657}
1658
Mingming Yin21854652016-04-13 11:54:02 -07001659static int check_and_set_hdmi_config(struct audio_device *adev,
1660 uint32_t channels,
1661 uint32_t sample_rate,
1662 audio_format_t format,
1663 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001664{
1665 struct listnode *node;
1666 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001667 int32_t factor = 1;
1668 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001669
Mingming Yin21854652016-04-13 11:54:02 -07001670 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1671 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001672
Mingming Yin21854652016-04-13 11:54:02 -07001673 if (channels != adev->cur_hdmi_channels) {
1674 ALOGV("channel does not match current hdmi channels");
1675 config = true;
1676 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001677
Mingming Yin21854652016-04-13 11:54:02 -07001678 if (sample_rate != adev->cur_hdmi_sample_rate) {
1679 ALOGV("sample rate does not match current hdmi sample rate");
1680 config = true;
1681 }
1682
1683 if (format != adev->cur_hdmi_format) {
1684 ALOGV("format does not match current hdmi format");
1685 config = true;
1686 }
1687
1688 /* TBD - add check for bit width */
1689 if (!config) {
1690 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001691 return 0;
1692 }
1693
Mingming Yin21854652016-04-13 11:54:02 -07001694 if (enable_passthru &&
1695 (format == AUDIO_FORMAT_E_AC3)) {
1696 ALOGV("factor 4 for E_AC3 passthru");
1697 factor = 4;
1698 }
1699
1700 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1701 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001702 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001703 adev->cur_hdmi_format = format;
1704 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001705
1706 /*
1707 * Deroute all the playback streams routed to HDMI so that
1708 * the back end is deactivated. Note that backend will not
1709 * be deactivated if any one stream is connected to it.
1710 */
1711 list_for_each(node, &adev->usecase_list) {
1712 usecase = node_to_item(node, struct audio_usecase, list);
1713 if (usecase->type == PCM_PLAYBACK &&
1714 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001715 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001716 }
1717 }
1718
Mingming Yin21854652016-04-13 11:54:02 -07001719 bool was_active = audio_extn_keep_alive_is_active();
1720 if (was_active)
1721 audio_extn_keep_alive_stop();
1722
Eric Laurent07eeafd2013-10-06 12:52:49 -07001723 /*
1724 * Enable all the streams disabled above. Now the HDMI backend
1725 * will be activated with new channel configuration
1726 */
1727 list_for_each(node, &adev->usecase_list) {
1728 usecase = node_to_item(node, struct audio_usecase, list);
1729 if (usecase->type == PCM_PLAYBACK &&
1730 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001731 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001732 }
1733 }
1734
Mingming Yin21854652016-04-13 11:54:02 -07001735 if (was_active)
1736 audio_extn_keep_alive_start();
1737
Eric Laurent07eeafd2013-10-06 12:52:49 -07001738 return 0;
1739}
1740
Mingming Yin21854652016-04-13 11:54:02 -07001741/* called with out lock taken */
1742static int check_and_set_hdmi_backend(struct stream_out *out)
1743{
1744 struct audio_device *adev = out->dev;
1745 int ret;
1746 bool enable_passthru = false;
1747
1748 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1749 return -1;
1750
1751 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1752
1753 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301754 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001755 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301756 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001757 }
1758
1759 /* Check if change in HDMI channel config is allowed */
1760 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1761 return -EPERM;
1762 }
1763
1764 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1765 uint32_t channels;
1766 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1767
1768 if (enable_passthru) {
1769 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301770 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001771 }
1772
1773 /* For pass through case, the backend should be configured as stereo */
1774 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1775 out->compr_config.codec->ch_in;
1776
1777 ret = check_and_set_hdmi_config(adev, channels,
1778 out->sample_rate, out->format,
1779 enable_passthru);
1780 } else
1781 ret = check_and_set_hdmi_config(adev, out->config.channels,
1782 out->config.rate,
1783 out->format,
1784 false);
1785 return ret;
1786}
1787
1788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789static int stop_output_stream(struct stream_out *out)
1790{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301791 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792 struct audio_usecase *uc_info;
1793 struct audio_device *adev = out->dev;
1794
Eric Laurent994a6932013-07-17 11:51:42 -07001795 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 uc_info = get_usecase_from_list(adev, out->usecase);
1798 if (uc_info == NULL) {
1799 ALOGE("%s: Could not find the usecase (%d) in the list",
1800 __func__, out->usecase);
1801 return -EINVAL;
1802 }
1803
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001804 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301805 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001806 if (adev->visualizer_stop_output != NULL)
1807 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001808
1809 audio_extn_dts_remove_state_notifier_node(out->usecase);
1810
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001811 if (adev->offload_effects_stop_output != NULL)
1812 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1813 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001814
Eric Laurent150dbfe2013-02-27 14:31:02 -08001815 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001816 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001817
1818 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001819 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001821 list_remove(&uc_info->list);
1822 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001824 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301825 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001826 ALOGV("Disable passthrough , reset mixer to pcm");
1827 /* NO_PASSTHROUGH */
1828 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001829
Mingming Yin21854652016-04-13 11:54:02 -07001830 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001831 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1832 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001833
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301834 /* Must be called after removing the usecase from list */
1835 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1836 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1837 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1838 DEFAULT_HDMI_OUT_FORMAT,
1839 false);
Eric Laurent994a6932013-07-17 11:51:42 -07001840 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 return ret;
1842}
1843
1844int start_output_stream(struct stream_out *out)
1845{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847 struct audio_usecase *uc_info;
1848 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301849 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001851 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1852 ret = -EINVAL;
1853 goto error_config;
1854 }
1855
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301856 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1857 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1858 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301859
Naresh Tanniru80659832014-06-04 18:17:56 +05301860 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301861 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301862 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301863 goto error_config;
1864 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301865
Eric Laurentb23d5282013-05-14 15:27:20 -07001866 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 if (out->pcm_device_id < 0) {
1868 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1869 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001870 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001871 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872 }
1873
1874 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001875
1876 if (!uc_info) {
1877 ret = -ENOMEM;
1878 goto error_config;
1879 }
1880
Mingming Yin21854652016-04-13 11:54:02 -07001881 /* This must be called before adding this usecase to the list */
1882 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1883 /* This call can fail if compress pass thru is already active */
1884 check_and_set_hdmi_backend(out);
1885 }
1886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887 uc_info->id = out->usecase;
1888 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001889 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001890 uc_info->devices = out->devices;
1891 uc_info->in_snd_device = SND_DEVICE_NONE;
1892 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001893 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301895 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1896 adev->perf_lock_opts,
1897 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 select_devices(adev, out->usecase);
1899
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001900 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1901 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001902 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001903 unsigned int flags = PCM_OUT;
1904 unsigned int pcm_open_retry_count = 0;
1905 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1906 flags |= PCM_MMAP | PCM_NOIRQ;
1907 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1908 } else
1909 flags |= PCM_MONOTONIC;
1910
1911 while (1) {
1912 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1913 flags, &out->config);
1914 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1915 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1916 if (out->pcm != NULL) {
1917 pcm_close(out->pcm);
1918 out->pcm = NULL;
1919 }
1920 if (pcm_open_retry_count-- == 0) {
1921 ret = -EIO;
1922 goto error_open;
1923 }
1924 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1925 continue;
1926 }
1927 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001928 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001929
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001930 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1931 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001932
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001933 ALOGV("%s: pcm_prepare", __func__);
1934 if (pcm_is_ready(out->pcm)) {
1935 ret = pcm_prepare(out->pcm);
1936 if (ret < 0) {
1937 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1938 pcm_close(out->pcm);
1939 out->pcm = NULL;
1940 goto error_open;
1941 }
1942 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001944 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1945 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001947 out->compr = compress_open(adev->snd_card,
1948 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001949 COMPRESS_IN, &out->compr_config);
1950 if (out->compr && !is_compress_ready(out->compr)) {
1951 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1952 compress_close(out->compr);
1953 out->compr = NULL;
1954 ret = -EIO;
1955 goto error_open;
1956 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301957 /* compress_open sends params of the track, so reset the flag here */
1958 out->is_compr_metadata_avail = false;
1959
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960 if (out->offload_callback)
1961 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001962
Fred Oh3f43e742015-03-04 18:42:34 -08001963 /* Since small bufs uses blocking writes, a write will be blocked
1964 for the default max poll time (20s) in the event of an SSR.
1965 Reduce the poll time to observe and deal with SSR faster.
1966 */
Ashish Jain5106d362016-05-11 19:23:33 +05301967 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001968 compress_set_max_poll_wait(out->compr, 1000);
1969 }
1970
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001971 audio_extn_dts_create_state_notifier_node(out->usecase);
1972 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1973 popcount(out->channel_mask),
1974 out->playback_started);
1975
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001976#ifdef DS1_DOLBY_DDP_ENABLED
1977 if (audio_extn_is_dolby_format(out->format))
1978 audio_extn_dolby_send_ddp_endp_params(adev);
1979#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301980 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001981 if (adev->visualizer_start_output != NULL)
1982 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1983 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301984 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001985 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301988 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001989 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001992error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301993 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001995error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301996 /*
1997 * sleep 50ms to allow sufficient time for kernel
1998 * drivers to recover incases like SSR.
1999 */
2000 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002001 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002}
2003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004static int check_input_parameters(uint32_t sample_rate,
2005 audio_format_t format,
2006 int channel_count)
2007{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002008 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302010 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2011 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2012 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002013 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302014 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002015
2016 switch (channel_count) {
2017 case 1:
2018 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302019 case 3:
2020 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002021 case 6:
2022 break;
2023 default:
2024 ret = -EINVAL;
2025 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026
2027 switch (sample_rate) {
2028 case 8000:
2029 case 11025:
2030 case 12000:
2031 case 16000:
2032 case 22050:
2033 case 24000:
2034 case 32000:
2035 case 44100:
2036 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302037 case 96000:
2038 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 break;
2040 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002041 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 }
2043
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002044 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045}
2046
2047static size_t get_input_buffer_size(uint32_t sample_rate,
2048 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002049 int channel_count,
2050 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051{
2052 size_t size = 0;
2053
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002054 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2055 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002057 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002058 if (is_low_latency)
2059 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302060
2061 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002063 /* make sure the size is multiple of 32 bytes
2064 * At 48 kHz mono 16-bit PCM:
2065 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2066 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2067 */
2068 size += 0x1f;
2069 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002070
2071 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072}
2073
Ashish Jain5106d362016-05-11 19:23:33 +05302074static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2075{
2076 uint64_t actual_frames_rendered = 0;
2077 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2078
2079 /* This adjustment accounts for buffering after app processor.
2080 * It is based on estimated DSP latency per use case, rather than exact.
2081 */
2082 int64_t platform_latency = platform_render_latency(out->usecase) *
2083 out->sample_rate / 1000000LL;
2084
2085 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2086 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2087 * hence only estimate.
2088 */
2089 int64_t signed_frames = out->written - kernel_buffer_size;
2090
2091 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2092
2093 if (signed_frames > 0)
2094 actual_frames_rendered = signed_frames;
2095
2096 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2097 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2098 (long long int)out->written, (int)kernel_buffer_size,
2099 audio_bytes_per_sample(out->compr_config.codec->format),
2100 popcount(out->channel_mask));
2101
2102 return actual_frames_rendered;
2103}
2104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2106{
2107 struct stream_out *out = (struct stream_out *)stream;
2108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110}
2111
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002112static int out_set_sample_rate(struct audio_stream *stream __unused,
2113 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114{
2115 return -ENOSYS;
2116}
2117
2118static size_t out_get_buffer_size(const struct audio_stream *stream)
2119{
2120 struct stream_out *out = (struct stream_out *)stream;
2121
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002122 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002123 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002124 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2125 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002127 return out->config.period_size *
2128 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129}
2130
2131static uint32_t out_get_channels(const struct audio_stream *stream)
2132{
2133 struct stream_out *out = (struct stream_out *)stream;
2134
2135 return out->channel_mask;
2136}
2137
2138static audio_format_t out_get_format(const struct audio_stream *stream)
2139{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 struct stream_out *out = (struct stream_out *)stream;
2141
2142 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143}
2144
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002145static int out_set_format(struct audio_stream *stream __unused,
2146 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147{
2148 return -ENOSYS;
2149}
2150
2151static int out_standby(struct audio_stream *stream)
2152{
2153 struct stream_out *out = (struct stream_out *)stream;
2154 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302156 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2157 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002158 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2159 /* Ignore standby in case of voip call because the voip output
2160 * stream is closed in adev_close_output_stream()
2161 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302162 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002163 return 0;
2164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002166 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002168 if (adev->adm_deregister_stream)
2169 adev->adm_deregister_stream(adev->adm_data, out->handle);
2170
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002171 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002173 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 if (out->pcm) {
2175 pcm_close(out->pcm);
2176 out->pcm = NULL;
2177 }
2178 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002179 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302181 out->send_next_track_params = false;
2182 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002183 out->gapless_mdata.encoder_delay = 0;
2184 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 if (out->compr != NULL) {
2186 compress_close(out->compr);
2187 out->compr = NULL;
2188 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002191 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 }
2193 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302194 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 return 0;
2196}
2197
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002198static int out_dump(const struct audio_stream *stream __unused,
2199 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200{
2201 return 0;
2202}
2203
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002204static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2205{
2206 int ret = 0;
2207 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002208
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002209 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002210 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002211 return -EINVAL;
2212 }
2213
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302214 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002215
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002216 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2217 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302218 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002219 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002220 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2221 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302222 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002223 }
2224
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002225 ALOGV("%s new encoder delay %u and padding %u", __func__,
2226 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2227
2228 return 0;
2229}
2230
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002231static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2232{
2233 return out == adev->primary_output || out == adev->voice_tx_output;
2234}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2237{
2238 struct stream_out *out = (struct stream_out *)stream;
2239 struct audio_device *adev = out->dev;
2240 struct str_parms *parms;
2241 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002242 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243
sangwoobc677242013-08-08 16:53:43 +09002244 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002245 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302247 if (!parms)
2248 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002249 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2250 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002252 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002253 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002256 * When HDMI cable is unplugged the music playback is paused and
2257 * the policy manager sends routing=0. But the audioflinger continues
2258 * to write data until standby time (3sec). As the HDMI core is
2259 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002260 * Avoid this by routing audio to speaker until standby.
2261 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002262 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2263 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302264 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002265 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2266 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002267 }
2268
2269 /*
2270 * select_devices() call below switches all the usecases on the same
2271 * backend to the new device. Refer to check_usecases_codec_backend() in
2272 * the select_devices(). But how do we undo this?
2273 *
2274 * For example, music playback is active on headset (deep-buffer usecase)
2275 * and if we go to ringtones and select a ringtone, low-latency usecase
2276 * will be started on headset+speaker. As we can't enable headset+speaker
2277 * and headset devices at the same time, select_devices() switches the music
2278 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2279 * So when the ringtone playback is completed, how do we undo the same?
2280 *
2281 * We are relying on the out_set_parameters() call on deep-buffer output,
2282 * once the ringtone playback is ended.
2283 * NOTE: We should not check if the current devices are same as new devices.
2284 * Because select_devices() must be called to switch back the music
2285 * playback to headset.
2286 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002287 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002288 out->devices = val;
2289
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302290 if (!out->standby) {
2291 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2292 adev->perf_lock_opts,
2293 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002294 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302295 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2296 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002297
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002298 if (output_drives_call(adev, out)) {
2299 if(!voice_is_in_call(adev)) {
2300 if (adev->mode == AUDIO_MODE_IN_CALL) {
2301 adev->current_call_output = out;
2302 ret = voice_start_call(adev);
2303 }
2304 } else {
2305 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002306 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002307 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002308 }
2309 }
2310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002312 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002314
2315 if (out == adev->primary_output) {
2316 pthread_mutex_lock(&adev->lock);
2317 audio_extn_set_parameters(adev, parms);
2318 pthread_mutex_unlock(&adev->lock);
2319 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002320 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002321 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002322 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002323
2324 audio_extn_dts_create_state_notifier_node(out->usecase);
2325 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2326 popcount(out->channel_mask),
2327 out->playback_started);
2328
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002329 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002330 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302333error:
Eric Laurent994a6932013-07-17 11:51:42 -07002334 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 return ret;
2336}
2337
2338static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2339{
2340 struct stream_out *out = (struct stream_out *)stream;
2341 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002342 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 char value[256];
2344 struct str_parms *reply = str_parms_create();
2345 size_t i, j;
2346 int ret;
2347 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002348
2349 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002350 if (reply) {
2351 str_parms_destroy(reply);
2352 }
2353 if (query) {
2354 str_parms_destroy(query);
2355 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002356 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2357 return NULL;
2358 }
2359
Eric Laurent994a6932013-07-17 11:51:42 -07002360 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2362 if (ret >= 0) {
2363 value[0] = '\0';
2364 i = 0;
2365 while (out->supported_channel_masks[i] != 0) {
2366 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2367 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2368 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002369 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002371 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002372 first = false;
2373 break;
2374 }
2375 }
2376 i++;
2377 }
2378 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2379 str = str_parms_to_str(reply);
2380 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002381 voice_extn_out_get_parameters(out, query, reply);
2382 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002383 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002384 free(str);
2385 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002386 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002388
Alexy Joseph62142aa2015-11-16 15:10:34 -08002389
2390 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2391 if (ret >= 0) {
2392 value[0] = '\0';
2393 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2394 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302395 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002396 } else {
2397 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302398 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002399 }
2400 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002401 if (str)
2402 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002403 str = str_parms_to_str(reply);
2404 }
2405
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002406 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2407 if (ret >= 0) {
2408 value[0] = '\0';
2409 i = 0;
2410 first = true;
2411 while (out->supported_formats[i] != 0) {
2412 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2413 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2414 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002415 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002416 }
2417 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2418 first = false;
2419 break;
2420 }
2421 }
2422 i++;
2423 }
2424 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002425 if (str)
2426 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002427 str = str_parms_to_str(reply);
2428 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002429
2430 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2431 if (ret >= 0) {
2432 value[0] = '\0';
2433 i = 0;
2434 first = true;
2435 while (out->supported_sample_rates[i] != 0) {
2436 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2437 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2438 if (!first) {
2439 strlcat(value, "|", sizeof(value));
2440 }
2441 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2442 first = false;
2443 break;
2444 }
2445 }
2446 i++;
2447 }
2448 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2449 if (str)
2450 free(str);
2451 str = str_parms_to_str(reply);
2452 }
2453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454 str_parms_destroy(query);
2455 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002456 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 return str;
2458}
2459
2460static uint32_t out_get_latency(const struct audio_stream_out *stream)
2461{
2462 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002463 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464
Alexy Josephaa54c872014-12-03 02:46:47 -08002465 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002466 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002467 } else {
2468 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002469 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002470 }
2471
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302472 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002473 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474}
2475
2476static int out_set_volume(struct audio_stream_out *stream, float left,
2477 float right)
2478{
Eric Laurenta9024de2013-04-04 09:19:12 -07002479 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 int volume[2];
2481
Eric Laurenta9024de2013-04-04 09:19:12 -07002482 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2483 /* only take left channel into account: the API is for stereo anyway */
2484 out->muted = (left == 0.0f);
2485 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002486 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302487 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002488 /*
2489 * Set mute or umute on HDMI passthrough stream.
2490 * Only take left channel into account.
2491 * Mute is 0 and unmute 1
2492 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302493 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002494 } else {
2495 char mixer_ctl_name[128];
2496 struct audio_device *adev = out->dev;
2497 struct mixer_ctl *ctl;
2498 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002499 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002501 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2502 "Compress Playback %d Volume", pcm_device_id);
2503 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2504 if (!ctl) {
2505 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2506 __func__, mixer_ctl_name);
2507 return -EINVAL;
2508 }
2509 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2510 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2511 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2512 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002513 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002514 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 return -ENOSYS;
2517}
2518
2519static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2520 size_t bytes)
2521{
2522 struct stream_out *out = (struct stream_out *)stream;
2523 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302524 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002525 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002527 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302528
Naresh Tanniru80659832014-06-04 18:17:56 +05302529 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002530
Ashish Jainbbce4322016-02-16 13:25:27 +05302531 if (is_offload_usecase(out->usecase)) {
2532 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302533 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2534 pthread_mutex_unlock(&out->lock);
2535 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302536 } else {
2537 /* increase written size during SSR to avoid mismatch
2538 * with the written frames count in AF
2539 */
2540 out->written += bytes / (out->config.channels * sizeof(short));
2541 ALOGD(" %s: sound card is not active/SSR state", __func__);
2542 ret= -EIO;
2543 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302544 }
2545 }
2546
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302547 if (audio_extn_passthru_should_drop_data(out)) {
2548 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2549 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2550 out_get_sample_rate(&out->stream.common));
2551 goto exit;
2552 }
2553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002555 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002556 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002557 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2558 ret = voice_extn_compress_voip_start_output_stream(out);
2559 else
2560 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002561 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002562 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002564 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 goto exit;
2566 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002567
2568 if (last_known_cal_step != -1) {
2569 ALOGD("%s: retry previous failed cal level set", __func__);
2570 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2571 }
2572
vivek mehta446c3962015-09-14 10:57:35 -07002573 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002574 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
Ashish Jain81eb2a82015-05-13 10:52:34 +05302577 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002578 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302579 adev->is_channel_status_set = true;
2580 }
2581
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002582 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002583 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002584 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002585 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002586 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2587 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302588 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2589 ALOGD("copl(%p):send next track params in gapless", out);
2590 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2591 out->send_next_track_params = false;
2592 out->is_compr_metadata_avail = false;
2593 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002594 }
2595
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302597 if (ret < 0)
2598 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302599 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002600 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302601 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302603 } else if (-ENETRESET == ret) {
2604 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2605 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2606 pthread_mutex_unlock(&out->lock);
2607 out_standby(&out->stream.common);
2608 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002609 }
Ashish Jain5106d362016-05-11 19:23:33 +05302610 if ( ret == (ssize_t)bytes && !out->non_blocking)
2611 out->written += bytes;
2612
Naresh Tanniru80659832014-06-04 18:17:56 +05302613 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002615 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 out->playback_started = 1;
2617 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002618
2619 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2620 popcount(out->channel_mask),
2621 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 }
2623 pthread_mutex_unlock(&out->lock);
2624 return ret;
2625 } else {
2626 if (out->pcm) {
2627 if (out->muted)
2628 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002629
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302630 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002631
2632 if (adev->adm_request_focus)
2633 adev->adm_request_focus(adev->adm_data, out->handle);
2634
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002635 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2636 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2637 else
2638 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002639
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302640 if (ret < 0)
2641 ret = -errno;
2642 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002643 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002644
2645 if (adev->adm_abandon_focus)
2646 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 }
2649
2650exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302651 /* ToDo: There may be a corner case when SSR happens back to back during
2652 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302653 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302654 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302655 }
2656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 pthread_mutex_unlock(&out->lock);
2658
2659 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002660 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002661 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302662 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302663 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302664 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302665 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302666 out->standby = true;
2667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302669 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302670 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672 return bytes;
2673}
2674
2675static int out_get_render_position(const struct audio_stream_out *stream,
2676 uint32_t *dsp_frames)
2677{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002678 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302679 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002680
2681 if (dsp_frames == NULL)
2682 return -EINVAL;
2683
2684 *dsp_frames = 0;
2685 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002686 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302687
2688 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2689 * this operation and adev_close_output_stream(where out gets reset).
2690 */
2691 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2692 *dsp_frames = get_actual_pcm_frames_rendered(out);
2693 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2694 return 0;
2695 }
2696
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002697 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302698 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302699 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302701 if (ret < 0)
2702 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002703 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302704 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002705 }
2706 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302707 if (-ENETRESET == ret) {
2708 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2709 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2710 return -EINVAL;
2711 } else if(ret < 0) {
2712 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2713 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302714 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2715 /*
2716 * Handle corner case where compress session is closed during SSR
2717 * and timestamp is queried
2718 */
2719 ALOGE(" ERROR: sound card not active, return error");
2720 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302721 } else {
2722 return 0;
2723 }
Zhou Song32a556e2015-05-05 10:46:56 +08002724 } else if (audio_is_linear_pcm(out->format)) {
2725 *dsp_frames = out->written;
2726 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002727 } else
2728 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729}
2730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002731static int out_add_audio_effect(const struct audio_stream *stream __unused,
2732 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733{
2734 return 0;
2735}
2736
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002737static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2738 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739{
2740 return 0;
2741}
2742
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002743static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2744 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745{
2746 return -EINVAL;
2747}
2748
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002749static int out_get_presentation_position(const struct audio_stream_out *stream,
2750 uint64_t *frames, struct timespec *timestamp)
2751{
2752 struct stream_out *out = (struct stream_out *)stream;
2753 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002754 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002755
Ashish Jain5106d362016-05-11 19:23:33 +05302756 /* below piece of code is not guarded against any lock because audioFliner serializes
2757 * this operation and adev_close_output_stream( where out gets reset).
2758 */
2759 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2760 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2761 *frames = get_actual_pcm_frames_rendered(out);
2762 /* this is the best we can do */
2763 clock_gettime(CLOCK_MONOTONIC, timestamp);
2764 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2765 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2766 return 0;
2767 }
2768
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002769 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002770
Ashish Jain5106d362016-05-11 19:23:33 +05302771 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2772 ret = compress_get_tstamp(out->compr, &dsp_frames,
2773 &out->sample_rate);
2774 ALOGVV("%s rendered frames %ld sample_rate %d",
2775 __func__, dsp_frames, out->sample_rate);
2776 *frames = dsp_frames;
2777 if (ret < 0)
2778 ret = -errno;
2779 if (-ENETRESET == ret) {
2780 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2781 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2782 ret = -EINVAL;
2783 } else
2784 ret = 0;
2785 /* this is the best we can do */
2786 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002787 } else {
2788 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002789 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002790 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2791 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002792 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002793 // This adjustment accounts for buffering after app processor.
2794 // It is based on estimated DSP latency per use case, rather than exact.
2795 signed_frames -=
2796 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2797
Eric Laurent949a0892013-09-20 09:20:13 -07002798 // It would be unusual for this value to be negative, but check just in case ...
2799 if (signed_frames >= 0) {
2800 *frames = signed_frames;
2801 ret = 0;
2802 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002803 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302804 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2805 *frames = out->written;
2806 clock_gettime(CLOCK_MONOTONIC, timestamp);
2807 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002808 }
2809 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002810 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002811 return ret;
2812}
2813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814static int out_set_callback(struct audio_stream_out *stream,
2815 stream_callback_t callback, void *cookie)
2816{
2817 struct stream_out *out = (struct stream_out *)stream;
2818
2819 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002820 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 out->offload_callback = callback;
2822 out->offload_cookie = cookie;
2823 pthread_mutex_unlock(&out->lock);
2824 return 0;
2825}
2826
2827static int out_pause(struct audio_stream_out* stream)
2828{
2829 struct stream_out *out = (struct stream_out *)stream;
2830 int status = -ENOSYS;
2831 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002832 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002833 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002834 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302836 struct audio_device *adev = out->dev;
2837 int snd_scard_state = get_snd_card_state(adev);
2838
2839 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2840 status = compress_pause(out->compr);
2841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002843
Mingming Yin21854652016-04-13 11:54:02 -07002844 if (audio_extn_passthru_is_active()) {
2845 ALOGV("offload use case, pause passthru");
2846 audio_extn_passthru_on_pause(out);
2847 }
2848
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302849 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002850 audio_extn_dts_notify_playback_state(out->usecase, 0,
2851 out->sample_rate, popcount(out->channel_mask),
2852 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 }
2854 pthread_mutex_unlock(&out->lock);
2855 }
2856 return status;
2857}
2858
2859static int out_resume(struct audio_stream_out* stream)
2860{
2861 struct stream_out *out = (struct stream_out *)stream;
2862 int status = -ENOSYS;
2863 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002864 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002865 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002867 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302869 struct audio_device *adev = out->dev;
2870 int snd_scard_state = get_snd_card_state(adev);
2871
Mingming Yin21854652016-04-13 11:54:02 -07002872 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2873 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2874 pthread_mutex_lock(&out->dev->lock);
2875 ALOGV("offload resume, check and set hdmi backend again");
2876 check_and_set_hdmi_backend(out);
2877 pthread_mutex_unlock(&out->dev->lock);
2878 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302879 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002880 }
2881 if (!status) {
2882 out->offload_state = OFFLOAD_STATE_PLAYING;
2883 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302884 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002885 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2886 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 }
2888 pthread_mutex_unlock(&out->lock);
2889 }
2890 return status;
2891}
2892
2893static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2894{
2895 struct stream_out *out = (struct stream_out *)stream;
2896 int status = -ENOSYS;
2897 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002898 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002899 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2901 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2902 else
2903 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2904 pthread_mutex_unlock(&out->lock);
2905 }
2906 return status;
2907}
2908
2909static int out_flush(struct audio_stream_out* stream)
2910{
2911 struct stream_out *out = (struct stream_out *)stream;
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):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002915 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302917 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002919 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 return 0;
2921 }
2922 return -ENOSYS;
2923}
2924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925/** audio_stream_in implementation **/
2926static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2927{
2928 struct stream_in *in = (struct stream_in *)stream;
2929
2930 return in->config.rate;
2931}
2932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002933static int in_set_sample_rate(struct audio_stream *stream __unused,
2934 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935{
2936 return -ENOSYS;
2937}
2938
2939static size_t in_get_buffer_size(const struct audio_stream *stream)
2940{
2941 struct stream_in *in = (struct stream_in *)stream;
2942
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002943 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2944 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002945 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2946 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002947
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002948 return in->config.period_size *
2949 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950}
2951
2952static uint32_t in_get_channels(const struct audio_stream *stream)
2953{
2954 struct stream_in *in = (struct stream_in *)stream;
2955
2956 return in->channel_mask;
2957}
2958
2959static audio_format_t in_get_format(const struct audio_stream *stream)
2960{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002961 struct stream_in *in = (struct stream_in *)stream;
2962
2963 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964}
2965
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002966static int in_set_format(struct audio_stream *stream __unused,
2967 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968{
2969 return -ENOSYS;
2970}
2971
2972static int in_standby(struct audio_stream *stream)
2973{
2974 struct stream_in *in = (struct stream_in *)stream;
2975 struct audio_device *adev = in->dev;
2976 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302977 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2978 stream, in->usecase, use_case_table[in->usecase]);
2979
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002980 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2981 /* Ignore standby in case of voip call because the voip input
2982 * stream is closed in adev_close_input_stream()
2983 */
2984 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2985 return status;
2986 }
2987
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002988 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002989 if (!in->standby && in->is_st_session) {
2990 ALOGD("%s: sound trigger pcm stop lab", __func__);
2991 audio_extn_sound_trigger_stop_lab(in);
2992 in->standby = 1;
2993 }
2994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002996 if (adev->adm_deregister_stream)
2997 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2998
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002999 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003001 if (in->pcm) {
3002 pcm_close(in->pcm);
3003 in->pcm = NULL;
3004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003006 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 }
3008 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003009 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 return status;
3011}
3012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003013static int in_dump(const struct audio_stream *stream __unused,
3014 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015{
3016 return 0;
3017}
3018
3019static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3020{
3021 struct stream_in *in = (struct stream_in *)stream;
3022 struct audio_device *adev = in->dev;
3023 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003025 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303027 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 parms = str_parms_create_str(kvpairs);
3029
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303030 if (!parms)
3031 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003032 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003033 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003034
3035 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3036 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 val = atoi(value);
3038 /* no audio source uses val == 0 */
3039 if ((in->source != val) && (val != 0)) {
3040 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003041 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3042 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3043 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003044 (in->config.rate == 8000 || in->config.rate == 16000 ||
3045 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003046 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003047 err = voice_extn_compress_voip_open_input_stream(in);
3048 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003049 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003050 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003051 }
3052 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 }
3054 }
3055
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003056 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3057 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003059 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 in->device = val;
3061 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003062 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003063 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 }
3065 }
3066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003068 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069
3070 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303071error:
Eric Laurent994a6932013-07-17 11:51:42 -07003072 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 return ret;
3074}
3075
3076static char* in_get_parameters(const struct audio_stream *stream,
3077 const char *keys)
3078{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 struct stream_in *in = (struct stream_in *)stream;
3080 struct str_parms *query = str_parms_create_str(keys);
3081 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003082 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003083
3084 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003085 if (reply) {
3086 str_parms_destroy(reply);
3087 }
3088 if (query) {
3089 str_parms_destroy(query);
3090 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003091 ALOGE("in_get_parameters: failed to create query or reply");
3092 return NULL;
3093 }
3094
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003095 ALOGV("%s: enter: keys - %s", __func__, keys);
3096
3097 voice_extn_in_get_parameters(in, query, reply);
3098
3099 str = str_parms_to_str(reply);
3100 str_parms_destroy(query);
3101 str_parms_destroy(reply);
3102
3103 ALOGV("%s: exit: returns - %s", __func__, str);
3104 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105}
3106
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003107static int in_set_gain(struct audio_stream_in *stream __unused,
3108 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109{
3110 return 0;
3111}
3112
3113static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3114 size_t bytes)
3115{
3116 struct stream_in *in = (struct stream_in *)stream;
3117 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303118 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303119 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303120 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003122 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303123
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003124 if (in->is_st_session) {
3125 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3126 /* Read from sound trigger HAL */
3127 audio_extn_sound_trigger_read(in, buffer, bytes);
3128 pthread_mutex_unlock(&in->lock);
3129 return bytes;
3130 }
3131
Ashish Jainbbce4322016-02-16 13:25:27 +05303132 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003133 ALOGD(" %s: sound card is not active/SSR state", __func__);
3134 ret= -EIO;;
3135 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303136 }
3137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003139 pthread_mutex_lock(&adev->lock);
3140 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3141 ret = voice_extn_compress_voip_start_input_stream(in);
3142 else
3143 ret = start_input_stream(in);
3144 pthread_mutex_unlock(&adev->lock);
3145 if (ret != 0) {
3146 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 }
3148 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003149 if (adev->adm_register_input_stream)
3150 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003153 if (adev->adm_request_focus)
3154 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303157 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003158 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303159 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003160 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303161 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003162 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303163 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003164 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303165 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3166 if (bytes % 4 == 0) {
3167 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3168 int_buf_stream = buffer;
3169 for (size_t itt=0; itt < bytes/4 ; itt++) {
3170 int_buf_stream[itt] >>= 8;
3171 }
3172 } else {
3173 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3174 ret = -EINVAL;
3175 goto exit;
3176 }
3177 } if (ret < 0) {
3178 ret = -errno;
3179 }
3180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 }
3182
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003183 if (adev->adm_abandon_focus)
3184 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 /*
3187 * Instead of writing zeroes here, we could trust the hardware
3188 * to always provide zeroes when muted.
3189 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303190 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3191 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 memset(buffer, 0, bytes);
3193
3194exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303195 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303196 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003197 if (-ENETRESET == ret)
3198 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200 pthread_mutex_unlock(&in->lock);
3201
3202 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303203 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303204 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303205 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303206 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303207 in->standby = true;
3208 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303209 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003211 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303212 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303213 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 }
3215 return bytes;
3216}
3217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003218static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219{
3220 return 0;
3221}
3222
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003223static int add_remove_audio_effect(const struct audio_stream *stream,
3224 effect_handle_t effect,
3225 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003227 struct stream_in *in = (struct stream_in *)stream;
3228 int status = 0;
3229 effect_descriptor_t desc;
3230
3231 status = (*effect)->get_descriptor(effect, &desc);
3232 if (status != 0)
3233 return status;
3234
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003235 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003236 pthread_mutex_lock(&in->dev->lock);
3237 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3238 in->enable_aec != enable &&
3239 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3240 in->enable_aec = enable;
3241 if (!in->standby)
3242 select_devices(in->dev, in->usecase);
3243 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003244 if (in->enable_ns != enable &&
3245 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3246 in->enable_ns = enable;
3247 if (!in->standby)
3248 select_devices(in->dev, in->usecase);
3249 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003250 pthread_mutex_unlock(&in->dev->lock);
3251 pthread_mutex_unlock(&in->lock);
3252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 return 0;
3254}
3255
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003256static int in_add_audio_effect(const struct audio_stream *stream,
3257 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258{
Eric Laurent994a6932013-07-17 11:51:42 -07003259 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003260 return add_remove_audio_effect(stream, effect, true);
3261}
3262
3263static int in_remove_audio_effect(const struct audio_stream *stream,
3264 effect_handle_t effect)
3265{
Eric Laurent994a6932013-07-17 11:51:42 -07003266 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003267 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268}
3269
3270static int adev_open_output_stream(struct audio_hw_device *dev,
3271 audio_io_handle_t handle,
3272 audio_devices_t devices,
3273 audio_output_flags_t flags,
3274 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003275 struct audio_stream_out **stream_out,
3276 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277{
3278 struct audio_device *adev = (struct audio_device *)dev;
3279 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303280 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003281 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303284
3285 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3286 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003287 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303288 return -EINVAL;
3289 }
3290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3292
Mingming Yin3a941d42016-02-17 18:08:05 -08003293 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3294 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303295 devices, flags, &out->stream);
3296
3297
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003298 if (!out) {
3299 return -ENOMEM;
3300 }
3301
Haynes Mathew George204045b2015-02-25 20:32:03 -08003302 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003303 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003304 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 if (devices == AUDIO_DEVICE_NONE)
3307 devices = AUDIO_DEVICE_OUT_SPEAKER;
3308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 out->flags = flags;
3310 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003311 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003312 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003313 out->sample_rate = config->sample_rate;
3314 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3315 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003316 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003317 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003318 out->non_blocking = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319
Mingming Yin3a941d42016-02-17 18:08:05 -08003320 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3321 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3322 pthread_mutex_lock(&adev->lock);
3323 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3324 ret = read_hdmi_sink_caps(out);
3325 pthread_mutex_unlock(&adev->lock);
3326 if (ret != 0) {
3327 if (ret == -ENOSYS) {
3328 /* ignore and go with default */
3329 ret = 0;
3330 } else {
3331 ALOGE("error reading hdmi sink caps");
3332 goto error_open;
3333 }
3334 }
3335 }
3336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003338 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303339 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3340 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003341 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3342 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3343
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003344 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003345 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3346 /*
3347 * Do not handle stereo output in Multi-channel cases
3348 * Stereo case is handled in normal playback path
3349 */
3350 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3351 ret = AUDIO_CHANNEL_OUT_STEREO;
3352 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003353
3354 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3355 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003356 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003357 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003358 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003359
3360 if (config->sample_rate == 0)
3361 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3362 if (config->channel_mask == 0)
3363 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003364 if (config->format == 0)
3365 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003366
3367 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003368 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003369 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3371 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003373 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003375 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3376 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003377 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003378 ret = voice_extn_compress_voip_open_output_stream(out);
3379 if (ret != 0) {
3380 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3381 __func__, ret);
3382 goto error_open;
3383 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003384 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3385 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3388 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3389 ALOGE("%s: Unsupported Offload information", __func__);
3390 ret = -EINVAL;
3391 goto error_open;
3392 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003393
Mingming Yin3a941d42016-02-17 18:08:05 -08003394 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003395 if(config->offload_info.format == 0)
3396 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003397 if (config->offload_info.sample_rate == 0)
3398 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003399 }
3400
Mingming Yin90310102013-11-13 16:57:00 -08003401 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303402 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003403 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003404 ret = -EINVAL;
3405 goto error_open;
3406 }
3407
3408 out->compr_config.codec = (struct snd_codec *)
3409 calloc(1, sizeof(struct snd_codec));
3410
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003411 if (!out->compr_config.codec) {
3412 ret = -ENOMEM;
3413 goto error_open;
3414 }
3415
vivek mehta0ea887a2015-08-26 14:01:20 -07003416 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303417 out->stream.pause = out_pause;
3418 out->stream.flush = out_flush;
3419 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003420 out->usecase = get_offload_usecase(adev, true);
3421 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003422 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003423 out->stream.set_callback = out_set_callback;
3424 out->stream.pause = out_pause;
3425 out->stream.resume = out_resume;
3426 out->stream.drain = out_drain;
3427 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003428 out->usecase = get_offload_usecase(adev, false);
3429 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003430 }
vivek mehta446c3962015-09-14 10:57:35 -07003431
3432 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003433 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3434 config->format == 0 && config->sample_rate == 0 &&
3435 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003436 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003437 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3438 } else {
3439 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3440 ret = -EEXIST;
3441 goto error_open;
3442 }
vivek mehta446c3962015-09-14 10:57:35 -07003443 }
3444
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003445 if (config->offload_info.channel_mask)
3446 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003447 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003449 config->offload_info.channel_mask = config->channel_mask;
3450 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003451 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003452 out->sample_rate = config->offload_info.sample_rate;
3453
Mingming Yin3ee55c62014-08-04 14:23:35 -07003454 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003455
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303456 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3457 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3458 audio_extn_dolby_send_ddp_endp_params(adev);
3459 audio_extn_dolby_set_dmid(adev);
3460 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003461
Ashish Jain5106d362016-05-11 19:23:33 +05303462 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003463 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003464 platform_get_pcm_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303465 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303466 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003467 out->compr_config.fragment_size =
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303468 audio_extn_passthru_get_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303469 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003470 } else {
3471 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003472 platform_get_compress_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303473 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003474 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003475 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003476 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003477 out->compr_config.codec->bit_rate =
3478 config->offload_info.bit_rate;
3479 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003480 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303482 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003483 /*TODO: Do we need to change it for passthrough */
3484 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485
Manish Dewangana6fc5442015-08-24 20:30:31 +05303486 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3487 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3488 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3489 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
vivek mehta0ea887a2015-08-26 14:01:20 -07003490 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3491 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Ashish Jain5106d362016-05-11 19:23:33 +05303492 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
3493 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
3494 if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
Mingming Yin3ee55c62014-08-04 14:23:35 -07003495 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003496
Amit Shekhar6f461b12014-08-01 14:52:58 -07003497 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303498 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003499
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3501 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003502
Alexy Josephaa54c872014-12-03 02:46:47 -08003503
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003504 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303505 out->send_next_track_params = false;
3506 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003507 out->offload_state = OFFLOAD_STATE_IDLE;
3508 out->playback_started = 0;
3509
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003510 audio_extn_dts_create_state_notifier_node(out->usecase);
3511
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 create_offload_callback_thread(out);
3513 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3514 __func__, config->offload_info.version,
3515 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303516
3517 /* Disable gapless if any of the following is true
3518 * passthrough playback
3519 * AV playback
3520 * Direct PCM playback
3521 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303522 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303523 config->offload_info.has_video ||
3524 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3525 check_and_set_gapless_mode(adev, false);
3526 } else
3527 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003528
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303529 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003530 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3531 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003532 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303533 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003534 if (ret != 0) {
3535 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3536 __func__, ret);
3537 goto error_open;
3538 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003539 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3540 if (config->sample_rate == 0)
3541 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3542 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3543 config->sample_rate != 8000) {
3544 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3545 ret = -EINVAL;
3546 goto error_open;
3547 }
3548 out->sample_rate = config->sample_rate;
3549 out->config.rate = config->sample_rate;
3550 if (config->format == AUDIO_FORMAT_DEFAULT)
3551 config->format = AUDIO_FORMAT_PCM_16_BIT;
3552 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3553 config->format = AUDIO_FORMAT_PCM_16_BIT;
3554 ret = -EINVAL;
3555 goto error_open;
3556 }
3557 out->format = config->format;
3558 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3559 out->config = pcm_config_afe_proxy_playback;
3560 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003561 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3562 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3563 out->config = pcm_config_low_latency;
3564 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003565 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003566 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3568 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003570 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3571 format = AUDIO_FORMAT_PCM_16_BIT;
3572 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3573 out->config = pcm_config_deep_buffer;
3574 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003575 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003576 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003577 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003578 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003579 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003580 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 }
3582
Mingming Yin21854652016-04-13 11:54:02 -07003583 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3584 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003585 /* TODO remove this hardcoding and check why width is zero*/
3586 if (out->bit_width == 0)
3587 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003588 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3589 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003590 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303591 out->bit_width, out->channel_mask,
3592 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003593 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3594 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3595 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003596 if(adev->primary_output == NULL)
3597 adev->primary_output = out;
3598 else {
3599 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003600 ret = -EEXIST;
3601 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003602 }
3603 }
3604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 /* Check if this usecase is already existing */
3606 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003607 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3608 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003611 ret = -EEXIST;
3612 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 }
3614 pthread_mutex_unlock(&adev->lock);
3615
3616 out->stream.common.get_sample_rate = out_get_sample_rate;
3617 out->stream.common.set_sample_rate = out_set_sample_rate;
3618 out->stream.common.get_buffer_size = out_get_buffer_size;
3619 out->stream.common.get_channels = out_get_channels;
3620 out->stream.common.get_format = out_get_format;
3621 out->stream.common.set_format = out_set_format;
3622 out->stream.common.standby = out_standby;
3623 out->stream.common.dump = out_dump;
3624 out->stream.common.set_parameters = out_set_parameters;
3625 out->stream.common.get_parameters = out_get_parameters;
3626 out->stream.common.add_audio_effect = out_add_audio_effect;
3627 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3628 out->stream.get_latency = out_get_latency;
3629 out->stream.set_volume = out_set_volume;
3630 out->stream.write = out_write;
3631 out->stream.get_render_position = out_get_render_position;
3632 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003633 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003636 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003637 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638
3639 config->format = out->stream.common.get_format(&out->stream.common);
3640 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3641 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3642
3643 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303644 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003645 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003646
3647 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3648 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3649 popcount(out->channel_mask), out->playback_started);
3650
Eric Laurent994a6932013-07-17 11:51:42 -07003651 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003653
3654error_open:
3655 free(out);
3656 *stream_out = NULL;
3657 ALOGD("%s: exit: ret %d", __func__, ret);
3658 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659}
3660
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003661static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 struct audio_stream_out *stream)
3663{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 struct stream_out *out = (struct stream_out *)stream;
3665 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003666 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003667
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303668 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3669
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003670 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303671 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003672 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303673 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003674 if(ret != 0)
3675 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3676 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003677 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003678 out_standby(&stream->common);
3679
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003680 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003681 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003683 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003684 if (out->compr_config.codec != NULL)
3685 free(out->compr_config.codec);
3686 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003687
3688 if (adev->voice_tx_output == out)
3689 adev->voice_tx_output = NULL;
3690
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 pthread_cond_destroy(&out->cond);
3692 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003694 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695}
3696
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003697static void close_compress_sessions(struct audio_device *adev)
3698{
Mingming Yin7b762e72015-03-04 13:47:32 -08003699 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303700 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003701 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003702 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303703
3704 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003705 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303706 if (is_offload_usecase(usecase->id)) {
3707 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003708 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3709 out = usecase->stream.out;
3710 pthread_mutex_unlock(&adev->lock);
3711 out_standby(&out->stream.common);
3712 pthread_mutex_lock(&adev->lock);
3713 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303714 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003715 }
3716 pthread_mutex_unlock(&adev->lock);
3717}
3718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3720{
3721 struct audio_device *adev = (struct audio_device *)dev;
3722 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003724 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003725 int ret;
3726 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003728 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303731 if (!parms)
3732 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003733 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3734 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303735 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303736 if (strstr(snd_card_status, "OFFLINE")) {
3737 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303738 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003739 //close compress sessions on OFFLINE status
3740 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303741 } else if (strstr(snd_card_status, "ONLINE")) {
3742 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303743 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003744 //send dts hpx license if enabled
3745 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303746 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303747 }
3748
3749 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003750 status = voice_set_parameters(adev, parms);
3751 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003752 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003754 status = platform_set_parameters(adev->platform, parms);
3755 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003756 goto done;
3757
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003758 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3759 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003760 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3762 adev->bluetooth_nrec = true;
3763 else
3764 adev->bluetooth_nrec = false;
3765 }
3766
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003767 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3768 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3770 adev->screen_off = false;
3771 else
3772 adev->screen_off = true;
3773 }
3774
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003775 ret = str_parms_get_int(parms, "rotation", &val);
3776 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003777 bool reverse_speakers = false;
3778 switch(val) {
3779 // FIXME: note that the code below assumes that the speakers are in the correct placement
3780 // relative to the user when the device is rotated 90deg from its default rotation. This
3781 // assumption is device-specific, not platform-specific like this code.
3782 case 270:
3783 reverse_speakers = true;
3784 break;
3785 case 0:
3786 case 90:
3787 case 180:
3788 break;
3789 default:
3790 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003791 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003792 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003793 if (status == 0) {
3794 if (adev->speaker_lr_swap != reverse_speakers) {
3795 adev->speaker_lr_swap = reverse_speakers;
3796 // only update the selected device if there is active pcm playback
3797 struct audio_usecase *usecase;
3798 struct listnode *node;
3799 list_for_each(node, &adev->usecase_list) {
3800 usecase = node_to_item(node, struct audio_usecase, list);
3801 if (usecase->type == PCM_PLAYBACK) {
3802 select_devices(adev, usecase->id);
3803 break;
3804 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003805 }
3806 }
3807 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003808 }
3809
Mingming Yin514a8bc2014-07-29 15:22:21 -07003810 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3811 if (ret >= 0) {
3812 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3813 adev->bt_wb_speech_enabled = true;
3814 else
3815 adev->bt_wb_speech_enabled = false;
3816 }
3817
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003818 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3819 if (ret >= 0) {
3820 val = atoi(value);
3821 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3822 ALOGV("cache new edid");
3823 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003824 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3825 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07003826 /*
3827 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3828 * Per AudioPolicyManager, USB device is higher priority than WFD.
3829 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3830 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3831 * starting voice call on USB
3832 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003833 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3834 if (ret >= 0) {
3835 audio_extn_usb_add_device(val, atoi(value));
3836 }
vivek mehta344576a2016-04-12 18:56:03 -07003837 ALOGV("detected USB connect .. disable proxy");
3838 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003839 }
3840 }
3841
3842 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3843 if (ret >= 0) {
3844 val = atoi(value);
3845 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3846 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08003847 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003848 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3849 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
3850 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3851 if (ret >= 0) {
3852 audio_extn_usb_remove_device(val, atoi(value));
3853 }
vivek mehta344576a2016-04-12 18:56:03 -07003854 ALOGV("detected USB disconnect .. enable proxy");
3855 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003856 }
3857 }
3858
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003859 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003860
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003861done:
3862 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003863 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303864error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003865 ALOGV("%s: exit with code(%d)", __func__, status);
3866 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867}
3868
3869static char* adev_get_parameters(const struct audio_hw_device *dev,
3870 const char *keys)
3871{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003872 struct audio_device *adev = (struct audio_device *)dev;
3873 struct str_parms *reply = str_parms_create();
3874 struct str_parms *query = str_parms_create_str(keys);
3875 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303876 char value[256] = {0};
3877 int ret = 0;
3878
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003879 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003880 if (reply) {
3881 str_parms_destroy(reply);
3882 }
3883 if (query) {
3884 str_parms_destroy(query);
3885 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003886 ALOGE("adev_get_parameters: failed to create query or reply");
3887 return NULL;
3888 }
3889
Naresh Tannirud7205b62014-06-20 02:54:48 +05303890 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3891 sizeof(value));
3892 if (ret >=0) {
3893 int val = 1;
3894 pthread_mutex_lock(&adev->snd_card_status.lock);
3895 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3896 val = 0;
3897 pthread_mutex_unlock(&adev->snd_card_status.lock);
3898 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3899 goto exit;
3900 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003901
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003902 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003903 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003904 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003905 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303906 pthread_mutex_unlock(&adev->lock);
3907
Naresh Tannirud7205b62014-06-20 02:54:48 +05303908exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003909 str = str_parms_to_str(reply);
3910 str_parms_destroy(query);
3911 str_parms_destroy(reply);
3912
3913 ALOGV("%s: exit: returns - %s", __func__, str);
3914 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915}
3916
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003917static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918{
3919 return 0;
3920}
3921
3922static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3923{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003924 int ret;
3925 struct audio_device *adev = (struct audio_device *)dev;
3926 pthread_mutex_lock(&adev->lock);
3927 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003928 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003929 pthread_mutex_unlock(&adev->lock);
3930 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931}
3932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003933static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3934 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935{
3936 return -ENOSYS;
3937}
3938
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003939static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3940 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941{
3942 return -ENOSYS;
3943}
3944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003945static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3946 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947{
3948 return -ENOSYS;
3949}
3950
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003951static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3952 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953{
3954 return -ENOSYS;
3955}
3956
3957static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3958{
3959 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 pthread_mutex_lock(&adev->lock);
3962 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003963 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003965 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003966 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003967 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003968 adev->current_call_output = NULL;
3969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 }
3971 pthread_mutex_unlock(&adev->lock);
3972 return 0;
3973}
3974
3975static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3976{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003977 int ret;
3978
3979 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003980 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003981 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3982 pthread_mutex_unlock(&adev->lock);
3983
3984 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985}
3986
3987static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3988{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003989 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990 return 0;
3991}
3992
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003993static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994 const struct audio_config *config)
3995{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003996 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003998 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3999 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000}
4001
4002static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004003 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 audio_devices_t devices,
4005 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004006 struct audio_stream_in **stream_in,
4007 audio_input_flags_t flags __unused,
4008 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004009 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010{
4011 struct audio_device *adev = (struct audio_device *)dev;
4012 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004013 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004014 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004015 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304018 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4019 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022
4023 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004024
4025 if (!in) {
4026 ALOGE("failed to allocate input stream");
4027 return -ENOMEM;
4028 }
4029
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304030 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304031 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4032 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004033 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004034 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 in->stream.common.get_sample_rate = in_get_sample_rate;
4037 in->stream.common.set_sample_rate = in_set_sample_rate;
4038 in->stream.common.get_buffer_size = in_get_buffer_size;
4039 in->stream.common.get_channels = in_get_channels;
4040 in->stream.common.get_format = in_get_format;
4041 in->stream.common.set_format = in_set_format;
4042 in->stream.common.standby = in_standby;
4043 in->stream.common.dump = in_dump;
4044 in->stream.common.set_parameters = in_set_parameters;
4045 in->stream.common.get_parameters = in_get_parameters;
4046 in->stream.common.add_audio_effect = in_add_audio_effect;
4047 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4048 in->stream.set_gain = in_set_gain;
4049 in->stream.read = in_read;
4050 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4051
4052 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004053 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 in->standby = 1;
4056 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004057 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004058 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059
4060 /* Update config params with the requested sample rate and channels */
4061 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004062 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4063 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4064 is_low_latency = true;
4065#if LOW_LATENCY_CAPTURE_USE_CASE
4066 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4067#endif
4068 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004071 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304072 in->bit_width = 16;
4073 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004075 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304076 if (adev->mode != AUDIO_MODE_IN_CALL) {
4077 ret = -EINVAL;
4078 goto err_open;
4079 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004080 if (config->sample_rate == 0)
4081 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4082 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4083 config->sample_rate != 8000) {
4084 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4085 ret = -EINVAL;
4086 goto err_open;
4087 }
4088 if (config->format == AUDIO_FORMAT_DEFAULT)
4089 config->format = AUDIO_FORMAT_PCM_16_BIT;
4090 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4091 config->format = AUDIO_FORMAT_PCM_16_BIT;
4092 ret = -EINVAL;
4093 goto err_open;
4094 }
4095
4096 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4097 in->config = pcm_config_afe_proxy_record;
4098 in->config.channels = channel_count;
4099 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304100 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304101 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4102 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004103 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004104 audio_extn_compr_cap_format_supported(config->format) &&
4105 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004106 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004107 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304108 /* restrict 24 bit capture for unprocessed source only
4109 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4110 */
4111 if (config->format == AUDIO_FORMAT_DEFAULT) {
4112 config->format = AUDIO_FORMAT_PCM_16_BIT;
4113 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4114 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4115 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4116 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4117 bool ret_error = false;
4118 in->bit_width = 24;
4119 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4120 from HAL is 24_packed and 8_24
4121 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4122 24_packed return error indicating supported format is 24_packed
4123 *> In case of any other source requesting 24 bit or float return error
4124 indicating format supported is 16 bit only.
4125
4126 on error flinger will retry with supported format passed
4127 */
4128 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4129 (source != AUDIO_SOURCE_CAMCORDER)) {
4130 config->format = AUDIO_FORMAT_PCM_16_BIT;
4131 if( config->sample_rate > 48000)
4132 config->sample_rate = 48000;
4133 ret_error = true;
4134 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4135 in->config.format = PCM_FORMAT_S24_3LE;
4136 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4137 in->config.format = PCM_FORMAT_S24_LE;
4138 } else {
4139 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4140 ret_error = true;
4141 }
4142
4143 if (ret_error) {
4144 ret = -EINVAL;
4145 goto err_open;
4146 }
4147 }
4148
4149 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004150 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004151 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004152 buffer_size = get_input_buffer_size(config->sample_rate,
4153 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004154 channel_count,
4155 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004156 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004157 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4158 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4159 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004160 (in->config.rate == 8000 || in->config.rate == 16000 ||
4161 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004162 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4163 voice_extn_compress_voip_open_input_stream(in);
4164 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004167 /* This stream could be for sound trigger lab,
4168 get sound trigger pcm if present */
4169 audio_extn_sound_trigger_check_and_get_session(in);
4170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004172 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004173 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174
4175err_open:
4176 free(in);
4177 *stream_in = NULL;
4178 return ret;
4179}
4180
4181static void adev_close_input_stream(struct audio_hw_device *dev,
4182 struct audio_stream_in *stream)
4183{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004184 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004185 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004186 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304187
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304188 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004189
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304190 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004191 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304192
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004193 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304194 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004195 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304196 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004197 if (ret != 0)
4198 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4199 __func__, ret);
4200 } else
4201 in_standby(&stream->common);
4202
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004203 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004204 audio_extn_ssr_deinit();
4205 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206
Mingming Yine62d7842013-10-25 16:26:03 -07004207 if(audio_extn_compr_cap_enabled() &&
4208 audio_extn_compr_cap_format_supported(in->config.format))
4209 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004210
Mingming Yinfd7607b2016-01-22 12:48:44 -08004211 if (in->is_st_session) {
4212 ALOGV("%s: sound trigger pcm stop lab", __func__);
4213 audio_extn_sound_trigger_stop_lab(in);
4214 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004215 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 return;
4217}
4218
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004219static int adev_dump(const audio_hw_device_t *device __unused,
4220 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221{
4222 return 0;
4223}
4224
4225static int adev_close(hw_device_t *device)
4226{
4227 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004228
4229 if (!adev)
4230 return 0;
4231
4232 pthread_mutex_lock(&adev_init_lock);
4233
4234 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004235 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004236 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004237 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004238 audio_route_free(adev->audio_route);
4239 free(adev->snd_dev_ref_cnt);
4240 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004241 if (adev->adm_deinit)
4242 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004243 free(device);
4244 adev = NULL;
4245 }
4246 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 return 0;
4249}
4250
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004251/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4252 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4253 * just that it _might_ work.
4254 */
4255static int period_size_is_plausible_for_low_latency(int period_size)
4256{
4257 switch (period_size) {
4258 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004259 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004260 case 240:
4261 case 320:
4262 case 480:
4263 return 1;
4264 default:
4265 return 0;
4266 }
4267}
4268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269static int adev_open(const hw_module_t *module, const char *name,
4270 hw_device_t **device)
4271{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004272 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4274
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004275 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004276 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004277 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004278 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004279 ALOGD("%s: returning existing instance of adev", __func__);
4280 ALOGD("%s: exit", __func__);
4281 pthread_mutex_unlock(&adev_init_lock);
4282 return 0;
4283 }
4284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285 adev = calloc(1, sizeof(struct audio_device));
4286
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004287 if (!adev) {
4288 pthread_mutex_unlock(&adev_init_lock);
4289 return -ENOMEM;
4290 }
4291
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004292 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4295 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4296 adev->device.common.module = (struct hw_module_t *)module;
4297 adev->device.common.close = adev_close;
4298
4299 adev->device.init_check = adev_init_check;
4300 adev->device.set_voice_volume = adev_set_voice_volume;
4301 adev->device.set_master_volume = adev_set_master_volume;
4302 adev->device.get_master_volume = adev_get_master_volume;
4303 adev->device.set_master_mute = adev_set_master_mute;
4304 adev->device.get_master_mute = adev_get_master_mute;
4305 adev->device.set_mode = adev_set_mode;
4306 adev->device.set_mic_mute = adev_set_mic_mute;
4307 adev->device.get_mic_mute = adev_get_mic_mute;
4308 adev->device.set_parameters = adev_set_parameters;
4309 adev->device.get_parameters = adev_get_parameters;
4310 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4311 adev->device.open_output_stream = adev_open_output_stream;
4312 adev->device.close_output_stream = adev_close_output_stream;
4313 adev->device.open_input_stream = adev_open_input_stream;
4314 adev->device.close_input_stream = adev_close_input_stream;
4315 adev->device.dump = adev_dump;
4316
4317 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004319 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004320 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004323 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004324 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004325 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004326 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004327 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004328 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004329 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004330 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304331 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304332 adev->perf_lock_opts[0] = 0x101;
4333 adev->perf_lock_opts[1] = 0x20E;
4334 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304335
4336 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4337 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004339 adev->platform = platform_init(adev);
4340 if (!adev->platform) {
4341 free(adev->snd_dev_ref_cnt);
4342 free(adev);
4343 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4344 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004345 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004346 return -EINVAL;
4347 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004348
Naresh Tanniru4c630392014-05-12 01:05:52 +05304349 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4350
Eric Laurentc4aef752013-09-12 17:45:53 -07004351 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4352 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4353 if (adev->visualizer_lib == NULL) {
4354 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4355 } else {
4356 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4357 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004358 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004359 "visualizer_hal_start_output");
4360 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004361 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004362 "visualizer_hal_stop_output");
4363 }
4364 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004365 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004366 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004367
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004368 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4369 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4370 if (adev->offload_effects_lib == NULL) {
4371 ALOGE("%s: DLOPEN failed for %s", __func__,
4372 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4373 } else {
4374 ALOGV("%s: DLOPEN successful for %s", __func__,
4375 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4376 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304377 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004378 "offload_effects_bundle_hal_start_output");
4379 adev->offload_effects_stop_output =
4380 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4381 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004382 adev->offload_effects_set_hpx_state =
4383 (int (*)(bool))dlsym(adev->offload_effects_lib,
4384 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304385 adev->offload_effects_get_parameters =
4386 (void (*)(struct str_parms *, struct str_parms *))
4387 dlsym(adev->offload_effects_lib,
4388 "offload_effects_bundle_get_parameters");
4389 adev->offload_effects_set_parameters =
4390 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4391 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004392 }
4393 }
4394
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004395 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4396 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4397 if (adev->adm_lib == NULL) {
4398 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4399 } else {
4400 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4401 adev->adm_init = (adm_init_t)
4402 dlsym(adev->adm_lib, "adm_init");
4403 adev->adm_deinit = (adm_deinit_t)
4404 dlsym(adev->adm_lib, "adm_deinit");
4405 adev->adm_register_input_stream = (adm_register_input_stream_t)
4406 dlsym(adev->adm_lib, "adm_register_input_stream");
4407 adev->adm_register_output_stream = (adm_register_output_stream_t)
4408 dlsym(adev->adm_lib, "adm_register_output_stream");
4409 adev->adm_deregister_stream = (adm_deregister_stream_t)
4410 dlsym(adev->adm_lib, "adm_deregister_stream");
4411 adev->adm_request_focus = (adm_request_focus_t)
4412 dlsym(adev->adm_lib, "adm_request_focus");
4413 adev->adm_abandon_focus = (adm_abandon_focus_t)
4414 dlsym(adev->adm_lib, "adm_abandon_focus");
4415 }
4416 }
4417
Mingming Yin514a8bc2014-07-29 15:22:21 -07004418 adev->bt_wb_speech_enabled = false;
4419
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004420 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 *device = &adev->device.common;
4422
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004423 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4424 &adev->streams_output_cfg_list);
4425
Kiran Kandi910e1862013-10-29 13:29:42 -07004426 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004427
4428 char value[PROPERTY_VALUE_MAX];
4429 int trial;
4430 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4431 trial = atoi(value);
4432 if (period_size_is_plausible_for_low_latency(trial)) {
4433 pcm_config_low_latency.period_size = trial;
4434 pcm_config_low_latency.start_threshold = trial / 4;
4435 pcm_config_low_latency.avail_min = trial / 4;
4436 configured_low_latency_capture_period_size = trial;
4437 }
4438 }
4439 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4440 trial = atoi(value);
4441 if (period_size_is_plausible_for_low_latency(trial)) {
4442 configured_low_latency_capture_period_size = trial;
4443 }
4444 }
4445
vivek mehta446c3962015-09-14 10:57:35 -07004446 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004447 pthread_mutex_unlock(&adev_init_lock);
4448
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004449 if (adev->adm_init)
4450 adev->adm_data = adev->adm_init();
4451
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304452 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004453 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 return 0;
4455}
4456
4457static struct hw_module_methods_t hal_module_methods = {
4458 .open = adev_open,
4459};
4460
4461struct audio_module HAL_MODULE_INFO_SYM = {
4462 .common = {
4463 .tag = HARDWARE_MODULE_TAG,
4464 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4465 .hal_api_version = HARDWARE_HAL_API_VERSION,
4466 .id = AUDIO_HARDWARE_MODULE_ID,
4467 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004468 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 .methods = &hal_module_methods,
4470 },
4471};