blob: 17f71cc3d6c8ec3a3ef9cdbc12e1594faca20393 [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 ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800341 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530342 format == AUDIO_FORMAT_ALAC ||
343 format == AUDIO_FORMAT_APE ||
344 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800345 format == AUDIO_FORMAT_WMA ||
346 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800347 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700348
349 return false;
350}
351
352static int get_snd_codec_id(audio_format_t format)
353{
354 int id = 0;
355
Ashish Jainf9b78162014-08-25 20:36:25 +0530356 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700357 case AUDIO_FORMAT_MP3:
358 id = SND_AUDIOCODEC_MP3;
359 break;
360 case AUDIO_FORMAT_AAC:
361 id = SND_AUDIOCODEC_AAC;
362 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530363 case AUDIO_FORMAT_AAC_ADTS:
364 id = SND_AUDIOCODEC_AAC;
365 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700366 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800367 id = SND_AUDIOCODEC_PCM;
368 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700369 case AUDIO_FORMAT_FLAC:
370 id = SND_AUDIOCODEC_FLAC;
371 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530372 case AUDIO_FORMAT_ALAC:
373 id = SND_AUDIOCODEC_ALAC;
374 break;
375 case AUDIO_FORMAT_APE:
376 id = SND_AUDIOCODEC_APE;
377 break;
378 case AUDIO_FORMAT_VORBIS:
379 id = SND_AUDIOCODEC_VORBIS;
380 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800381 case AUDIO_FORMAT_WMA:
382 id = SND_AUDIOCODEC_WMA;
383 break;
384 case AUDIO_FORMAT_WMA_PRO:
385 id = SND_AUDIOCODEC_WMA_PRO;
386 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700387 default:
Mingming Yin90310102013-11-13 16:57:00 -0800388 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700389 }
390
391 return id;
392}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800393
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530394int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530395{
396 int snd_scard_state;
397
398 if (!adev)
399 return SND_CARD_STATE_OFFLINE;
400
401 pthread_mutex_lock(&adev->snd_card_status.lock);
402 snd_scard_state = adev->snd_card_status.state;
403 pthread_mutex_unlock(&adev->snd_card_status.lock);
404
405 return snd_scard_state;
406}
407
408static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
409{
410 if (!adev)
411 return -ENOSYS;
412
413 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700414 if (adev->snd_card_status.state != snd_scard_state) {
415 adev->snd_card_status.state = snd_scard_state;
416 platform_snd_card_update(adev->platform, snd_scard_state);
417 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530418 pthread_mutex_unlock(&adev->snd_card_status.lock);
419
420 return 0;
421}
422
Avinash Vaish71a8b972014-07-24 15:36:33 +0530423static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
424 struct audio_usecase *uc_info)
425{
426 struct listnode *node;
427 struct audio_usecase *usecase;
428
429 if (uc_info == NULL)
430 return -EINVAL;
431
432 /* Re-route all voice usecases on the shared backend other than the
433 specified usecase to new snd devices */
434 list_for_each(node, &adev->usecase_list) {
435 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800436 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530437 enable_audio_route(adev, usecase);
438 }
439 return 0;
440}
441
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700442int pcm_ioctl(struct pcm *pcm, int request, ...)
443{
444 va_list ap;
445 void * arg;
446 int pcm_fd = *(int*)pcm;
447
448 va_start(ap, request);
449 arg = va_arg(ap, void *);
450 va_end(ap);
451
452 return ioctl(pcm_fd, request, arg);
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700458 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700459 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800460
461 if (usecase == NULL)
462 return -EINVAL;
463
464 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
465
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700467 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800470
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800471#ifdef DS1_DOLBY_DAP_ENABLED
472 audio_extn_dolby_set_dmid(adev);
473 audio_extn_dolby_set_endpoint(adev);
474#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700475 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700476 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530477 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700478 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530479 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800480 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700481 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700482 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700483 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800484 ALOGV("%s: exit", __func__);
485 return 0;
486}
487
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700488int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700489 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800490{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700491 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700492 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800493
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530494 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800495 return -EINVAL;
496
497 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700498 if (usecase->type == PCM_CAPTURE)
499 snd_device = usecase->in_snd_device;
500 else
501 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800502 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700503 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700504 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700505 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700506 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530507 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800508 ALOGV("%s: exit", __func__);
509 return 0;
510}
511
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700513 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800514{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530515 int i, num_devices = 0;
516 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700517 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
518
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800519 if (snd_device < SND_DEVICE_MIN ||
520 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800521 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800522 return -EINVAL;
523 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700524
525 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700526
527 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
528 ALOGE("%s: Invalid sound device returned", __func__);
529 return -EINVAL;
530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700531 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700532 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700533 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700534 return 0;
535 }
536
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530537
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700538 if (audio_extn_spkr_prot_is_enabled())
539 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700540
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800542 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
543 audio_extn_spkr_prot_is_enabled()) {
544 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700545 adev->snd_dev_ref_cnt[snd_device]--;
546 return -EINVAL;
547 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200548 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800549 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800550 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200551 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800552 return -EINVAL;
553 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530554 } else if (platform_can_split_snd_device(adev->platform, snd_device,
555 &num_devices, new_snd_devices)) {
556 for (i = 0; i < num_devices; i++) {
557 enable_snd_device(adev, new_snd_devices[i]);
558 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700560 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700561 /* due to the possibility of calibration overwrite between listen
562 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700563 audio_extn_sound_trigger_update_device_status(snd_device,
564 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530565 audio_extn_listen_update_device_status(snd_device,
566 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700567 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700568 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700569 audio_extn_sound_trigger_update_device_status(snd_device,
570 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530571 audio_extn_listen_update_device_status(snd_device,
572 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700573 return -EINVAL;
574 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300575 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700576 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530577
578 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
579 !adev->native_playback_enabled &&
580 audio_is_true_native_stream_active(adev)) {
581 ALOGD("%s: %d: napb: enabling native mode in hardware",
582 __func__, __LINE__);
583 audio_route_apply_and_update_path(adev->audio_route,
584 "true-native-mode");
585 adev->native_playback_enabled = true;
586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800588 return 0;
589}
590
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700591int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700592 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800593{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530594 int i, num_devices = 0;
595 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700596 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
597
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800598 if (snd_device < SND_DEVICE_MIN ||
599 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800600 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800601 return -EINVAL;
602 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
604 ALOGE("%s: device ref cnt is already 0", __func__);
605 return -EINVAL;
606 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700607
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700609
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700610 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
611 ALOGE("%s: Invalid sound device returned", __func__);
612 return -EINVAL;
613 }
614
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700616 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800617 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
618 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700619 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530620 } else if (platform_can_split_snd_device(adev->platform, snd_device,
621 &num_devices, new_snd_devices)) {
622 for (i = 0; i < num_devices; i++) {
623 disable_snd_device(adev, new_snd_devices[i]);
624 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300625 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700626 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300627 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700628
Ashish Jain81eb2a82015-05-13 10:52:34 +0530629 if (snd_device == SND_DEVICE_OUT_HDMI)
630 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530631 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
632 adev->native_playback_enabled) {
633 ALOGD("%s: %d: napb: disabling native mode in hardware",
634 __func__, __LINE__);
635 audio_route_reset_and_update_path(adev->audio_route,
636 "true-native-mode");
637 adev->native_playback_enabled = false;
638 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530639
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200640 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700641 audio_extn_sound_trigger_update_device_status(snd_device,
642 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530643 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800644 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 return 0;
648}
649
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530651 struct audio_usecase *uc_info,
652 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653{
654 struct listnode *node;
655 struct audio_usecase *usecase;
656 bool switch_device[AUDIO_USECASE_MAX];
657 int i, num_uc_to_switch = 0;
658
659 /*
660 * This function is to make sure that all the usecases that are active on
661 * the hardware codec backend are always routed to any one device that is
662 * handled by the hardware codec.
663 * For example, if low-latency and deep-buffer usecases are currently active
664 * on speaker and out_set_parameters(headset) is received on low-latency
665 * output, then we have to make sure deep-buffer is also switched to headset,
666 * because of the limitation that both the devices cannot be enabled
667 * at the same time as they share the same backend.
668 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700669 /*
670 * This call is to check if we need to force routing for a particular stream
671 * If there is a backend configuration change for the device when a
672 * new stream starts, then ADM needs to be closed and re-opened with the new
673 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800674 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700675 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800676 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
677 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530678
679 ALOGD("%s:becf: force routing %d", __func__, force_routing);
680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800682 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800683 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 for (i = 0; i < AUDIO_USECASE_MAX; i++)
685 switch_device[i] = false;
686
687 list_for_each(node, &adev->usecase_list) {
688 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800689
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530690 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
691 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530692 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530693 platform_get_snd_device_name(usecase->out_snd_device),
694 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800695 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530696 usecase != uc_info &&
697 (usecase->out_snd_device != snd_device || force_routing) &&
698 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
699 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
700 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
701 __func__, use_case_table[usecase->id],
702 platform_get_snd_device_name(usecase->out_snd_device));
703 disable_audio_route(adev, usecase);
704 switch_device[usecase->id] = true;
705 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 }
707 }
708
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530709 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
710 num_uc_to_switch);
711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700713 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700714
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530715 /* Make sure the previous devices to be disabled first and then enable the
716 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700717 list_for_each(node, &adev->usecase_list) {
718 usecase = node_to_item(node, struct audio_usecase, list);
719 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700720 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
722 }
723
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
726 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700728 }
729 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700730
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731 /* Re-route all the usecases on the shared backend other than the
732 specified usecase to new snd devices */
733 list_for_each(node, &adev->usecase_list) {
734 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530735 /* Update the out_snd_device only before enabling the audio route */
736 if (switch_device[usecase->id]) {
737 usecase->out_snd_device = snd_device;
738 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530739 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530740 use_case_table[usecase->id],
741 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530742 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530743 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 }
745 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746 }
747}
748
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530749static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700750 struct audio_usecase *uc_info,
751 snd_device_t snd_device)
752{
753 struct listnode *node;
754 struct audio_usecase *usecase;
755 bool switch_device[AUDIO_USECASE_MAX];
756 int i, num_uc_to_switch = 0;
757
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530758 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
759 snd_device);
760 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700761 /*
762 * This function is to make sure that all the active capture usecases
763 * are always routed to the same input sound device.
764 * For example, if audio-record and voice-call usecases are currently
765 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
766 * is received for voice call then we have to make sure that audio-record
767 * usecase is also switched to earpiece i.e. voice-dmic-ef,
768 * because of the limitation that two devices cannot be enabled
769 * at the same time if they share the same backend.
770 */
771 for (i = 0; i < AUDIO_USECASE_MAX; i++)
772 switch_device[i] = false;
773
774 list_for_each(node, &adev->usecase_list) {
775 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800776 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700777 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530778 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700779 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530780 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
781 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700782 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700783 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
784 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700785 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700786 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 switch_device[usecase->id] = true;
788 num_uc_to_switch++;
789 }
790 }
791
792 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700793 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700794
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530795 /* Make sure the previous devices to be disabled first and then enable the
796 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700797 list_for_each(node, &adev->usecase_list) {
798 usecase = node_to_item(node, struct audio_usecase, list);
799 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700800 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800801 }
802 }
803
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
806 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700807 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700808 }
809 }
810
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700811 /* Re-route all the usecases on the shared backend other than the
812 specified usecase to new snd devices */
813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
815 /* Update the in_snd_device only before enabling the audio route */
816 if (switch_device[usecase->id] ) {
817 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800818 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530819 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700820 }
821 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700822 }
823}
824
Mingming Yin3a941d42016-02-17 18:08:05 -0800825static void reset_hdmi_sink_caps(struct stream_out *out) {
826 int i = 0;
827
828 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
829 out->supported_channel_masks[i] = 0;
830 }
831 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
832 out->supported_formats[i] = 0;
833 }
834 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
835 out->supported_sample_rates[i] = 0;
836 }
837}
838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800840static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841{
Mingming Yin3a941d42016-02-17 18:08:05 -0800842 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700843 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844
Mingming Yin3a941d42016-02-17 18:08:05 -0800845 reset_hdmi_sink_caps(out);
846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800847 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800848 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800849 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700850 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800851 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
852 case 6:
853 ALOGV("%s: HDMI supports 5.1 channels", __func__);
854 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
855 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
857 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
858 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
859 case 2:
860 ALOGV("%s: HDMI supports 2 channels", __func__);
861 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862 break;
863 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800864 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700865 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800866 break;
867 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800868
869 // check channel format caps
870 i = 0;
871 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
872 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
873 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
874 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
875 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
876 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
877 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
878 }
879
880 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
881 ALOGV(":%s HDMI supports DTS format", __func__);
882 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
883 }
884
885 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
886 ALOGV(":%s HDMI supports DTS HD format", __func__);
887 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
888 }
889
890
891 // check sample rate caps
892 i = 0;
893 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
894 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
895 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
896 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
897 }
898 }
899
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700900 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800901}
902
Alexy Josephb1379942016-01-29 15:49:38 -0800903audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800904 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700905{
906 struct audio_usecase *usecase;
907 struct listnode *node;
908
909 list_for_each(node, &adev->usecase_list) {
910 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800911 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700912 ALOGV("%s: usecase id %d", __func__, usecase->id);
913 return usecase->id;
914 }
915 }
916 return USECASE_INVALID;
917}
918
Alexy Josephb1379942016-01-29 15:49:38 -0800919struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700920 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921{
922 struct audio_usecase *usecase;
923 struct listnode *node;
924
925 list_for_each(node, &adev->usecase_list) {
926 usecase = node_to_item(node, struct audio_usecase, list);
927 if (usecase->id == uc_id)
928 return usecase;
929 }
930 return NULL;
931}
932
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530933/*
934 * is a true native playback active
935 */
936bool audio_is_true_native_stream_active(struct audio_device *adev)
937{
938 bool active = false;
939 int i = 0;
940 struct listnode *node;
941
942 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
943 ALOGV("%s:napb: not in true mode or non hdphones device",
944 __func__);
945 active = false;
946 goto exit;
947 }
948
949 list_for_each(node, &adev->usecase_list) {
950 struct audio_usecase *uc;
951 uc = node_to_item(node, struct audio_usecase, list);
952 struct stream_out *curr_out =
953 (struct stream_out*) uc->stream.out;
954
955 if (curr_out && PCM_PLAYBACK == uc->type) {
956 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
957 "(%d) device %s", __func__, i++, use_case_table[uc->id],
958 uc->id, curr_out->sample_rate,
959 curr_out->bit_width,
960 platform_get_snd_device_name(uc->out_snd_device));
961
962 if (is_offload_usecase(uc->id) &&
963 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
964 active = true;
965 ALOGD("%s:napb:native stream detected", __func__);
966 }
967 }
968 }
969exit:
970 return active;
971}
972
973
974static bool force_device_switch(struct audio_usecase *usecase)
975{
976 bool ret = false;
977 bool is_it_true_mode = false;
978
979 if (is_offload_usecase(usecase->id) &&
980 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800981 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
982 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
983 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530984 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
985 if ((is_it_true_mode && !adev->native_playback_enabled) ||
986 (!is_it_true_mode && adev->native_playback_enabled)){
987 ret = true;
988 ALOGD("napb: time to toggle native mode");
989 }
990 }
991
992 return ret;
993}
994
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700995int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800997 snd_device_t out_snd_device = SND_DEVICE_NONE;
998 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 struct audio_usecase *usecase = NULL;
1000 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001001 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001002 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001003 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301006 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1007
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008 usecase = get_usecase_from_list(adev, uc_id);
1009 if (usecase == NULL) {
1010 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1011 return -EINVAL;
1012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001014 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001015 (usecase->type == VOIP_CALL) ||
1016 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001017 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001018 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001019 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 usecase->devices = usecase->stream.out->devices;
1021 } else {
1022 /*
1023 * If the voice call is active, use the sound devices of voice call usecase
1024 * so that it would not result any device switch. All the usecases will
1025 * be switched to new device when select_devices() is called for voice call
1026 * usecase. This is to avoid switching devices for voice call when
1027 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001028 * choose voice call device only if the use case device is
1029 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001031 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001032 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001033 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001034 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1035 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1036 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037 in_snd_device = vc_usecase->in_snd_device;
1038 out_snd_device = vc_usecase->out_snd_device;
1039 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001040 } else if (voice_extn_compress_voip_is_active(adev)) {
1041 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001042 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301043 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001044 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001045 in_snd_device = voip_usecase->in_snd_device;
1046 out_snd_device = voip_usecase->out_snd_device;
1047 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001048 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001049 hfp_ucid = audio_extn_hfp_get_usecase();
1050 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001051 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001052 in_snd_device = hfp_usecase->in_snd_device;
1053 out_snd_device = hfp_usecase->out_snd_device;
1054 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001055 }
1056 if (usecase->type == PCM_PLAYBACK) {
1057 usecase->devices = usecase->stream.out->devices;
1058 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001059 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001060 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001061 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001062 if (usecase->stream.out == adev->primary_output &&
1063 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001064 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001065 select_devices(adev, adev->active_input->usecase);
1066 }
1067 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068 } else if (usecase->type == PCM_CAPTURE) {
1069 usecase->devices = usecase->stream.in->device;
1070 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001071 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001072 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001073 if (adev->active_input &&
1074 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301075 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1076 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1077 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001078 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001079 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001080 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1081 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001082 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001083 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001084 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 }
1086 }
1087
1088 if (out_snd_device == usecase->out_snd_device &&
1089 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301090
1091 if (!force_device_switch(usecase))
1092 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 }
1094
sangwoobc677242013-08-08 16:53:43 +09001095 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001096 out_snd_device, platform_get_snd_device_name(out_snd_device),
1097 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 /*
1100 * Limitation: While in call, to do a device switch we need to disable
1101 * and enable both RX and TX devices though one of them is same as current
1102 * device.
1103 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001104 if ((usecase->type == VOICE_CALL) &&
1105 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1106 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001107 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001108 }
1109
1110 if (((usecase->type == VOICE_CALL) ||
1111 (usecase->type == VOIP_CALL)) &&
1112 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1113 /* Disable sidetone only if voice/voip call already exists */
1114 if (voice_is_call_state_active(adev) ||
1115 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001116 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001117 }
1118
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119 /* Disable current sound devices */
1120 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001121 disable_audio_route(adev, usecase);
1122 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 }
1124
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001126 disable_audio_route(adev, usecase);
1127 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128 }
1129
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001130 /* Applicable only on the targets that has external modem.
1131 * New device information should be sent to modem before enabling
1132 * the devices to reduce in-call device switch time.
1133 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001134 if ((usecase->type == VOICE_CALL) &&
1135 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1136 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001137 status = platform_switch_voice_call_enable_device_config(adev->platform,
1138 out_snd_device,
1139 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001140 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001141
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 /* Enable new sound devices */
1143 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001144 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001145 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 }
1147
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001148 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301149 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001150 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152
Avinash Vaish71a8b972014-07-24 15:36:33 +05301153 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001154 status = platform_switch_voice_call_device_post(adev->platform,
1155 out_snd_device,
1156 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301157 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001158 /* Enable sidetone only if voice/voip call already exists */
1159 if (voice_is_call_state_active(adev) ||
1160 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001161 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301162 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001163
sangwoo170731f2013-06-08 15:36:36 +09001164 usecase->in_snd_device = in_snd_device;
1165 usecase->out_snd_device = out_snd_device;
1166
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301167 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001168 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301169 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001170 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301171 usecase->stream.out->flags,
1172 usecase->stream.out->format,
1173 usecase->stream.out->sample_rate,
1174 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301175 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301176 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001177 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301178 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001179
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001180 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001181
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001182 /* Applicable only on the targets that has external modem.
1183 * Enable device command should be sent to modem only after
1184 * enabling voice call mixer controls
1185 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001186 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001187 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1188 out_snd_device,
1189 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301190 ALOGD("%s: done",__func__);
1191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001192 return status;
1193}
1194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195static int stop_input_stream(struct stream_in *in)
1196{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301197 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 struct audio_usecase *uc_info;
1199 struct audio_device *adev = in->dev;
1200
Eric Laurentc8400632013-02-14 19:04:54 -08001201 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202
Eric Laurent994a6932013-07-17 11:51:42 -07001203 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001205 uc_info = get_usecase_from_list(adev, in->usecase);
1206 if (uc_info == NULL) {
1207 ALOGE("%s: Could not find the usecase (%d) in the list",
1208 __func__, in->usecase);
1209 return -EINVAL;
1210 }
1211
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001212 /* Close in-call recording streams */
1213 voice_check_and_stop_incall_rec_usecase(adev, in);
1214
Eric Laurent150dbfe2013-02-27 14:31:02 -08001215 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001216 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217
1218 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001219 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001221 list_remove(&uc_info->list);
1222 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223
Eric Laurent994a6932013-07-17 11:51:42 -07001224 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 return ret;
1226}
1227
1228int start_input_stream(struct stream_in *in)
1229{
1230 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001231 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 struct audio_usecase *uc_info;
1233 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301234 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235
Mingming Yin2664a5b2015-09-03 10:53:11 -07001236 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1237 if (get_usecase_from_list(adev, usecase) == NULL)
1238 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301239 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1240 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001241
Naresh Tanniru80659832014-06-04 18:17:56 +05301242
1243 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301244 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301245 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301246 goto error_config;
1247 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301248
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001249 /* Check if source matches incall recording usecase criteria */
1250 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1251 if (ret)
1252 goto error_config;
1253 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001254 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1255
1256 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1257 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1258 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001259 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001260 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001261
Eric Laurentb23d5282013-05-14 15:27:20 -07001262 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 if (in->pcm_device_id < 0) {
1264 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1265 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001266 ret = -EINVAL;
1267 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269
1270 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001272
1273 if (!uc_info) {
1274 ret = -ENOMEM;
1275 goto error_config;
1276 }
1277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278 uc_info->id = in->usecase;
1279 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001280 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 uc_info->devices = in->device;
1282 uc_info->in_snd_device = SND_DEVICE_NONE;
1283 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001285 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301286 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1287 adev->perf_lock_opts,
1288 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301291 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1292 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001293
1294 unsigned int flags = PCM_IN;
1295 unsigned int pcm_open_retry_count = 0;
1296
1297 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1298 flags |= PCM_MMAP | PCM_NOIRQ;
1299 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1300 }
1301
1302 while (1) {
1303 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1304 flags, &in->config);
1305 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1306 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1307 if (in->pcm != NULL) {
1308 pcm_close(in->pcm);
1309 in->pcm = NULL;
1310 }
1311 if (pcm_open_retry_count-- == 0) {
1312 ret = -EIO;
1313 goto error_open;
1314 }
1315 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1316 continue;
1317 }
1318 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001319 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001320
1321 ALOGV("%s: pcm_prepare", __func__);
1322 ret = pcm_prepare(in->pcm);
1323 if (ret < 0) {
1324 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1325 pcm_close(in->pcm);
1326 in->pcm = NULL;
1327 goto error_open;
1328 }
1329
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301330 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001331 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001332
Eric Laurentc8400632013-02-14 19:04:54 -08001333 return ret;
1334
1335error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301336 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001338error_config:
1339 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301340 /*
1341 * sleep 50ms to allow sufficient time for kernel
1342 * drivers to recover incases like SSR.
1343 */
1344 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001345 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001346
1347 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348}
1349
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001350void lock_input_stream(struct stream_in *in)
1351{
1352 pthread_mutex_lock(&in->pre_lock);
1353 pthread_mutex_lock(&in->lock);
1354 pthread_mutex_unlock(&in->pre_lock);
1355}
1356
1357void lock_output_stream(struct stream_out *out)
1358{
1359 pthread_mutex_lock(&out->pre_lock);
1360 pthread_mutex_lock(&out->lock);
1361 pthread_mutex_unlock(&out->pre_lock);
1362}
1363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001364/* must be called with out->lock locked */
1365static int send_offload_cmd_l(struct stream_out* out, int command)
1366{
1367 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1368
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001369 if (!cmd) {
1370 ALOGE("failed to allocate mem for command 0x%x", command);
1371 return -ENOMEM;
1372 }
1373
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001374 ALOGVV("%s %d", __func__, command);
1375
1376 cmd->cmd = command;
1377 list_add_tail(&out->offload_cmd_list, &cmd->node);
1378 pthread_cond_signal(&out->offload_cond);
1379 return 0;
1380}
1381
1382/* must be called iwth out->lock locked */
1383static void stop_compressed_output_l(struct stream_out *out)
1384{
1385 out->offload_state = OFFLOAD_STATE_IDLE;
1386 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001387 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001388 if (out->compr != NULL) {
1389 compress_stop(out->compr);
1390 while (out->offload_thread_blocked) {
1391 pthread_cond_wait(&out->cond, &out->lock);
1392 }
1393 }
1394}
1395
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001396bool is_offload_usecase(audio_usecase_t uc_id)
1397{
1398 unsigned int i;
1399 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1400 if (uc_id == offload_usecases[i])
1401 return true;
1402 }
1403 return false;
1404}
1405
vivek mehta446c3962015-09-14 10:57:35 -07001406static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001407{
vivek mehta446c3962015-09-14 10:57:35 -07001408 audio_usecase_t ret_uc = USECASE_INVALID;
1409 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001410 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001411 if (!adev->multi_offload_enable) {
1412 if (is_direct_pcm)
1413 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1414 else
1415 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001416
vivek mehta446c3962015-09-14 10:57:35 -07001417 pthread_mutex_lock(&adev->lock);
1418 if (get_usecase_from_list(adev, ret_uc) != NULL)
1419 ret_uc = USECASE_INVALID;
1420 pthread_mutex_unlock(&adev->lock);
1421
1422 return ret_uc;
1423 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001424
1425 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001426 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1427 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1428 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1429 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001430 break;
1431 }
1432 }
vivek mehta446c3962015-09-14 10:57:35 -07001433
1434 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1435 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001436}
1437
1438static void free_offload_usecase(struct audio_device *adev,
1439 audio_usecase_t uc_id)
1440{
vivek mehta446c3962015-09-14 10:57:35 -07001441 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001442 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001443
1444 if (!adev->multi_offload_enable)
1445 return;
1446
1447 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1448 if (offload_usecases[offload_uc_index] == uc_id) {
1449 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001450 break;
1451 }
1452 }
1453 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1454}
1455
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001456static void *offload_thread_loop(void *context)
1457{
1458 struct stream_out *out = (struct stream_out *) context;
1459 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001460 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001461
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001462 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1463 set_sched_policy(0, SP_FOREGROUND);
1464 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1465
1466 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001467 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 for (;;) {
1469 struct offload_cmd *cmd = NULL;
1470 stream_callback_event_t event;
1471 bool send_callback = false;
1472
1473 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1474 __func__, list_empty(&out->offload_cmd_list),
1475 out->offload_state);
1476 if (list_empty(&out->offload_cmd_list)) {
1477 ALOGV("%s SLEEPING", __func__);
1478 pthread_cond_wait(&out->offload_cond, &out->lock);
1479 ALOGV("%s RUNNING", __func__);
1480 continue;
1481 }
1482
1483 item = list_head(&out->offload_cmd_list);
1484 cmd = node_to_item(item, struct offload_cmd, node);
1485 list_remove(item);
1486
1487 ALOGVV("%s STATE %d CMD %d out->compr %p",
1488 __func__, out->offload_state, cmd->cmd, out->compr);
1489
1490 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1491 free(cmd);
1492 break;
1493 }
1494
1495 if (out->compr == NULL) {
1496 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001497 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001498 pthread_cond_signal(&out->cond);
1499 continue;
1500 }
1501 out->offload_thread_blocked = true;
1502 pthread_mutex_unlock(&out->lock);
1503 send_callback = false;
1504 switch(cmd->cmd) {
1505 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001506 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001507 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001508 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001509 send_callback = true;
1510 event = STREAM_CBK_EVENT_WRITE_READY;
1511 break;
1512 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001513 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301514 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001515 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301516 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001517 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301518 if (ret < 0)
1519 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301520 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301521 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001522 compress_drain(out->compr);
1523 else
1524 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301525 if (ret != -ENETRESET) {
1526 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301527 pthread_mutex_lock(&out->lock);
1528 out->send_new_metadata = 1;
1529 out->send_next_track_params = true;
1530 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301531 event = STREAM_CBK_EVENT_DRAIN_READY;
1532 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1533 } else
1534 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001535 break;
1536 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001537 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001538 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001539 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 send_callback = true;
1541 event = STREAM_CBK_EVENT_DRAIN_READY;
1542 break;
1543 default:
1544 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1545 break;
1546 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001547 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001548 out->offload_thread_blocked = false;
1549 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001550 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001551 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001553 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001554 free(cmd);
1555 }
1556
1557 pthread_cond_signal(&out->cond);
1558 while (!list_empty(&out->offload_cmd_list)) {
1559 item = list_head(&out->offload_cmd_list);
1560 list_remove(item);
1561 free(node_to_item(item, struct offload_cmd, node));
1562 }
1563 pthread_mutex_unlock(&out->lock);
1564
1565 return NULL;
1566}
1567
1568static int create_offload_callback_thread(struct stream_out *out)
1569{
1570 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1571 list_init(&out->offload_cmd_list);
1572 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1573 offload_thread_loop, out);
1574 return 0;
1575}
1576
1577static int destroy_offload_callback_thread(struct stream_out *out)
1578{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001579 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580 stop_compressed_output_l(out);
1581 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1582
1583 pthread_mutex_unlock(&out->lock);
1584 pthread_join(out->offload_thread, (void **) NULL);
1585 pthread_cond_destroy(&out->offload_cond);
1586
1587 return 0;
1588}
1589
Mingming Yin21854652016-04-13 11:54:02 -07001590static bool allow_hdmi_channel_config(struct audio_device *adev,
1591 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001592{
1593 struct listnode *node;
1594 struct audio_usecase *usecase;
1595 bool ret = true;
1596
Mingming Yin21854652016-04-13 11:54:02 -07001597 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1598 ret = false;
1599 goto exit;
1600 }
1601
1602 if (audio_extn_passthru_is_active()) {
1603 ALOGI("%s: Compress audio passthrough is active,"
1604 "no HDMI config change allowed", __func__);
1605 ret = false;
1606 goto exit;
1607 }
1608
Eric Laurent07eeafd2013-10-06 12:52:49 -07001609 list_for_each(node, &adev->usecase_list) {
1610 usecase = node_to_item(node, struct audio_usecase, list);
1611 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1612 /*
1613 * If voice call is already existing, do not proceed further to avoid
1614 * disabling/enabling both RX and TX devices, CSD calls, etc.
1615 * Once the voice call done, the HDMI channels can be configured to
1616 * max channels of remaining use cases.
1617 */
1618 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001619 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001620 __func__);
1621 ret = false;
1622 break;
1623 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001624 if (!enable_passthru) {
1625 ALOGV("%s: multi channel playback is active, "
1626 "no change in HDMI channels", __func__);
1627 ret = false;
1628 break;
1629 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001630 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001631 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001632 if (!enable_passthru) {
1633 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1634 ", no change in HDMI channels", __func__,
1635 usecase->stream.out->channel_mask);
1636 ret = false;
1637 break;
1638 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001639 }
1640 }
1641 }
Mingming Yin21854652016-04-13 11:54:02 -07001642 ALOGV("allow hdmi config %d", ret);
1643exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001644 return ret;
1645}
1646
Mingming Yin21854652016-04-13 11:54:02 -07001647static int check_and_set_hdmi_config(struct audio_device *adev,
1648 uint32_t channels,
1649 uint32_t sample_rate,
1650 audio_format_t format,
1651 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001652{
1653 struct listnode *node;
1654 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001655 int32_t factor = 1;
1656 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001657
Mingming Yin21854652016-04-13 11:54:02 -07001658 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1659 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001660
Mingming Yin21854652016-04-13 11:54:02 -07001661 if (channels != adev->cur_hdmi_channels) {
1662 ALOGV("channel does not match current hdmi channels");
1663 config = true;
1664 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001665
Mingming Yin21854652016-04-13 11:54:02 -07001666 if (sample_rate != adev->cur_hdmi_sample_rate) {
1667 ALOGV("sample rate does not match current hdmi sample rate");
1668 config = true;
1669 }
1670
1671 if (format != adev->cur_hdmi_format) {
1672 ALOGV("format does not match current hdmi format");
1673 config = true;
1674 }
1675
1676 /* TBD - add check for bit width */
1677 if (!config) {
1678 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001679 return 0;
1680 }
1681
Mingming Yin21854652016-04-13 11:54:02 -07001682 if (enable_passthru &&
1683 (format == AUDIO_FORMAT_E_AC3)) {
1684 ALOGV("factor 4 for E_AC3 passthru");
1685 factor = 4;
1686 }
1687
1688 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1689 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001690 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001691 adev->cur_hdmi_format = format;
1692 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001693
1694 /*
1695 * Deroute all the playback streams routed to HDMI so that
1696 * the back end is deactivated. Note that backend will not
1697 * be deactivated if any one stream is connected to it.
1698 */
1699 list_for_each(node, &adev->usecase_list) {
1700 usecase = node_to_item(node, struct audio_usecase, list);
1701 if (usecase->type == PCM_PLAYBACK &&
1702 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001703 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001704 }
1705 }
1706
Mingming Yin21854652016-04-13 11:54:02 -07001707 bool was_active = audio_extn_keep_alive_is_active();
1708 if (was_active)
1709 audio_extn_keep_alive_stop();
1710
Eric Laurent07eeafd2013-10-06 12:52:49 -07001711 /*
1712 * Enable all the streams disabled above. Now the HDMI backend
1713 * will be activated with new channel configuration
1714 */
1715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
1717 if (usecase->type == PCM_PLAYBACK &&
1718 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001719 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001720 }
1721 }
1722
Mingming Yin21854652016-04-13 11:54:02 -07001723 if (was_active)
1724 audio_extn_keep_alive_start();
1725
Eric Laurent07eeafd2013-10-06 12:52:49 -07001726 return 0;
1727}
1728
Mingming Yin21854652016-04-13 11:54:02 -07001729/* called with out lock taken */
1730static int check_and_set_hdmi_backend(struct stream_out *out)
1731{
1732 struct audio_device *adev = out->dev;
1733 int ret;
1734 bool enable_passthru = false;
1735
1736 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1737 return -1;
1738
1739 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1740
1741 if (is_offload_usecase(out->usecase) &&
1742 audio_extn_dolby_is_passthrough_stream(out)) {
1743 enable_passthru = true;
1744 }
1745
1746 /* Check if change in HDMI channel config is allowed */
1747 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1748 return -EPERM;
1749 }
1750
1751 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1752 uint32_t channels;
1753 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1754
1755 if (enable_passthru) {
1756 audio_extn_passthru_on_start(out);
1757 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1758 }
1759
1760 /* For pass through case, the backend should be configured as stereo */
1761 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1762 out->compr_config.codec->ch_in;
1763
1764 ret = check_and_set_hdmi_config(adev, channels,
1765 out->sample_rate, out->format,
1766 enable_passthru);
1767 } else
1768 ret = check_and_set_hdmi_config(adev, out->config.channels,
1769 out->config.rate,
1770 out->format,
1771 false);
1772 return ret;
1773}
1774
1775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776static int stop_output_stream(struct stream_out *out)
1777{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301778 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779 struct audio_usecase *uc_info;
1780 struct audio_device *adev = out->dev;
1781
Eric Laurent994a6932013-07-17 11:51:42 -07001782 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001783 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 uc_info = get_usecase_from_list(adev, out->usecase);
1785 if (uc_info == NULL) {
1786 ALOGE("%s: Could not find the usecase (%d) in the list",
1787 __func__, out->usecase);
1788 return -EINVAL;
1789 }
1790
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001791 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001792 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001793 if (adev->visualizer_stop_output != NULL)
1794 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001795
1796 audio_extn_dts_remove_state_notifier_node(out->usecase);
1797
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001798 if (adev->offload_effects_stop_output != NULL)
1799 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1800 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001801
Eric Laurent150dbfe2013-02-27 14:31:02 -08001802 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001803 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001804
1805 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001806 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001808 list_remove(&uc_info->list);
1809 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001811 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001812 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001813 ALOGV("Disable passthrough , reset mixer to pcm");
1814 /* NO_PASSTHROUGH */
1815 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001816
1817 /* Must be called after removing the usecase from list */
1818 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1819 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1820 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1821 DEFAULT_HDMI_OUT_FORMAT,
1822 false);
1823 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001824 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1825 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001826
Eric Laurent994a6932013-07-17 11:51:42 -07001827 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828 return ret;
1829}
1830
1831int start_output_stream(struct stream_out *out)
1832{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 struct audio_usecase *uc_info;
1835 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301836 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001838 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1839 ret = -EINVAL;
1840 goto error_config;
1841 }
1842
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301843 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1844 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1845 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301846
Naresh Tanniru80659832014-06-04 18:17:56 +05301847 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301848 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301849 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301850 goto error_config;
1851 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301852
Eric Laurentb23d5282013-05-14 15:27:20 -07001853 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 if (out->pcm_device_id < 0) {
1855 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1856 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001857 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001858 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 }
1860
1861 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001862
1863 if (!uc_info) {
1864 ret = -ENOMEM;
1865 goto error_config;
1866 }
1867
Mingming Yin21854652016-04-13 11:54:02 -07001868 /* This must be called before adding this usecase to the list */
1869 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1870 /* This call can fail if compress pass thru is already active */
1871 check_and_set_hdmi_backend(out);
1872 }
1873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 uc_info->id = out->usecase;
1875 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001876 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 uc_info->devices = out->devices;
1878 uc_info->in_snd_device = SND_DEVICE_NONE;
1879 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001880 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301882 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1883 adev->perf_lock_opts,
1884 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885 select_devices(adev, out->usecase);
1886
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001887 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1888 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001889 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001890 unsigned int flags = PCM_OUT;
1891 unsigned int pcm_open_retry_count = 0;
1892 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1893 flags |= PCM_MMAP | PCM_NOIRQ;
1894 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1895 } else
1896 flags |= PCM_MONOTONIC;
1897
1898 while (1) {
1899 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1900 flags, &out->config);
1901 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1902 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1903 if (out->pcm != NULL) {
1904 pcm_close(out->pcm);
1905 out->pcm = NULL;
1906 }
1907 if (pcm_open_retry_count-- == 0) {
1908 ret = -EIO;
1909 goto error_open;
1910 }
1911 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1912 continue;
1913 }
1914 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001915 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001916
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001917 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1918 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001919
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001920 ALOGV("%s: pcm_prepare", __func__);
1921 if (pcm_is_ready(out->pcm)) {
1922 ret = pcm_prepare(out->pcm);
1923 if (ret < 0) {
1924 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1925 pcm_close(out->pcm);
1926 out->pcm = NULL;
1927 goto error_open;
1928 }
1929 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001931 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1932 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001934 out->compr = compress_open(adev->snd_card,
1935 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001936 COMPRESS_IN, &out->compr_config);
1937 if (out->compr && !is_compress_ready(out->compr)) {
1938 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1939 compress_close(out->compr);
1940 out->compr = NULL;
1941 ret = -EIO;
1942 goto error_open;
1943 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301944 /* compress_open sends params of the track, so reset the flag here */
1945 out->is_compr_metadata_avail = false;
1946
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001947 if (out->offload_callback)
1948 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001949
Fred Oh3f43e742015-03-04 18:42:34 -08001950 /* Since small bufs uses blocking writes, a write will be blocked
1951 for the default max poll time (20s) in the event of an SSR.
1952 Reduce the poll time to observe and deal with SSR faster.
1953 */
Ashish Jain5106d362016-05-11 19:23:33 +05301954 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001955 compress_set_max_poll_wait(out->compr, 1000);
1956 }
1957
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001958 audio_extn_dts_create_state_notifier_node(out->usecase);
1959 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1960 popcount(out->channel_mask),
1961 out->playback_started);
1962
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001963#ifdef DS1_DOLBY_DDP_ENABLED
1964 if (audio_extn_is_dolby_format(out->format))
1965 audio_extn_dolby_send_ddp_endp_params(adev);
1966#endif
Mingming Yin21854652016-04-13 11:54:02 -07001967 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001968 if (adev->visualizer_start_output != NULL)
1969 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1970 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301971 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001972 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001973 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301975 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001976 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001979error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301980 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001982error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301983 /*
1984 * sleep 50ms to allow sufficient time for kernel
1985 * drivers to recover incases like SSR.
1986 */
1987 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001988 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989}
1990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991static int check_input_parameters(uint32_t sample_rate,
1992 audio_format_t format,
1993 int channel_count)
1994{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001995 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301997 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1998 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
1999 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002000 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302001 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002002
2003 switch (channel_count) {
2004 case 1:
2005 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302006 case 3:
2007 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002008 case 6:
2009 break;
2010 default:
2011 ret = -EINVAL;
2012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013
2014 switch (sample_rate) {
2015 case 8000:
2016 case 11025:
2017 case 12000:
2018 case 16000:
2019 case 22050:
2020 case 24000:
2021 case 32000:
2022 case 44100:
2023 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302024 case 96000:
2025 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 break;
2027 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002028 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 }
2030
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002031 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032}
2033
2034static size_t get_input_buffer_size(uint32_t sample_rate,
2035 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002036 int channel_count,
2037 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038{
2039 size_t size = 0;
2040
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002041 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2042 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002044 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002045 if (is_low_latency)
2046 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302047
2048 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002050 /* make sure the size is multiple of 32 bytes
2051 * At 48 kHz mono 16-bit PCM:
2052 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2053 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2054 */
2055 size += 0x1f;
2056 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002057
2058 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059}
2060
Ashish Jain5106d362016-05-11 19:23:33 +05302061static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2062{
2063 uint64_t actual_frames_rendered = 0;
2064 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2065
2066 /* This adjustment accounts for buffering after app processor.
2067 * It is based on estimated DSP latency per use case, rather than exact.
2068 */
2069 int64_t platform_latency = platform_render_latency(out->usecase) *
2070 out->sample_rate / 1000000LL;
2071
2072 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2073 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2074 * hence only estimate.
2075 */
2076 int64_t signed_frames = out->written - kernel_buffer_size;
2077
2078 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2079
2080 if (signed_frames > 0)
2081 actual_frames_rendered = signed_frames;
2082
2083 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2084 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2085 (long long int)out->written, (int)kernel_buffer_size,
2086 audio_bytes_per_sample(out->compr_config.codec->format),
2087 popcount(out->channel_mask));
2088
2089 return actual_frames_rendered;
2090}
2091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2093{
2094 struct stream_out *out = (struct stream_out *)stream;
2095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097}
2098
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002099static int out_set_sample_rate(struct audio_stream *stream __unused,
2100 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101{
2102 return -ENOSYS;
2103}
2104
2105static size_t out_get_buffer_size(const struct audio_stream *stream)
2106{
2107 struct stream_out *out = (struct stream_out *)stream;
2108
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002109 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002111 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2112 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002114 return out->config.period_size *
2115 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116}
2117
2118static uint32_t out_get_channels(const struct audio_stream *stream)
2119{
2120 struct stream_out *out = (struct stream_out *)stream;
2121
2122 return out->channel_mask;
2123}
2124
2125static audio_format_t out_get_format(const struct audio_stream *stream)
2126{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 struct stream_out *out = (struct stream_out *)stream;
2128
2129 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130}
2131
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002132static int out_set_format(struct audio_stream *stream __unused,
2133 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134{
2135 return -ENOSYS;
2136}
2137
2138static int out_standby(struct audio_stream *stream)
2139{
2140 struct stream_out *out = (struct stream_out *)stream;
2141 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302143 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2144 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002145 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2146 /* Ignore standby in case of voip call because the voip output
2147 * stream is closed in adev_close_output_stream()
2148 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302149 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002150 return 0;
2151 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002153 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002155 if (adev->adm_deregister_stream)
2156 adev->adm_deregister_stream(adev->adm_data, out->handle);
2157
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002158 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002160 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 if (out->pcm) {
2162 pcm_close(out->pcm);
2163 out->pcm = NULL;
2164 }
2165 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002166 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302168 out->send_next_track_params = false;
2169 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 out->gapless_mdata.encoder_delay = 0;
2171 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 if (out->compr != NULL) {
2173 compress_close(out->compr);
2174 out->compr = NULL;
2175 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002176 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002178 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 }
2180 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302181 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 return 0;
2183}
2184
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002185static int out_dump(const struct audio_stream *stream __unused,
2186 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187{
2188 return 0;
2189}
2190
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002191static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2192{
2193 int ret = 0;
2194 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002195
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002196 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002197 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002198 return -EINVAL;
2199 }
2200
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302201 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002202
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002203 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2204 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302205 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002206 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002207 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2208 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302209 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002210 }
2211
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002212 ALOGV("%s new encoder delay %u and padding %u", __func__,
2213 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2214
2215 return 0;
2216}
2217
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002218static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2219{
2220 return out == adev->primary_output || out == adev->voice_tx_output;
2221}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2224{
2225 struct stream_out *out = (struct stream_out *)stream;
2226 struct audio_device *adev = out->dev;
2227 struct str_parms *parms;
2228 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002229 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230
sangwoobc677242013-08-08 16:53:43 +09002231 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002232 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302234 if (!parms)
2235 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002236 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2237 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002239 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002240 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002242 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002243 * When HDMI cable is unplugged the music playback is paused and
2244 * the policy manager sends routing=0. But the audioflinger continues
2245 * to write data until standby time (3sec). As the HDMI core is
2246 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 * Avoid this by routing audio to speaker until standby.
2248 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002249 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2250 (val == AUDIO_DEVICE_NONE) &&
2251 !audio_extn_dolby_is_passthrough_stream(out) &&
2252 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2253 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002254 }
2255
2256 /*
2257 * select_devices() call below switches all the usecases on the same
2258 * backend to the new device. Refer to check_usecases_codec_backend() in
2259 * the select_devices(). But how do we undo this?
2260 *
2261 * For example, music playback is active on headset (deep-buffer usecase)
2262 * and if we go to ringtones and select a ringtone, low-latency usecase
2263 * will be started on headset+speaker. As we can't enable headset+speaker
2264 * and headset devices at the same time, select_devices() switches the music
2265 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2266 * So when the ringtone playback is completed, how do we undo the same?
2267 *
2268 * We are relying on the out_set_parameters() call on deep-buffer output,
2269 * once the ringtone playback is ended.
2270 * NOTE: We should not check if the current devices are same as new devices.
2271 * Because select_devices() must be called to switch back the music
2272 * playback to headset.
2273 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002274 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002275 out->devices = val;
2276
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302277 if (!out->standby) {
2278 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2279 adev->perf_lock_opts,
2280 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302282 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2283 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002284
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002285 if (output_drives_call(adev, out)) {
2286 if(!voice_is_in_call(adev)) {
2287 if (adev->mode == AUDIO_MODE_IN_CALL) {
2288 adev->current_call_output = out;
2289 ret = voice_start_call(adev);
2290 }
2291 } else {
2292 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002293 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002294 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002295 }
2296 }
2297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002299 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002301
2302 if (out == adev->primary_output) {
2303 pthread_mutex_lock(&adev->lock);
2304 audio_extn_set_parameters(adev, parms);
2305 pthread_mutex_unlock(&adev->lock);
2306 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002307 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002308 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002309 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002310
2311 audio_extn_dts_create_state_notifier_node(out->usecase);
2312 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2313 popcount(out->channel_mask),
2314 out->playback_started);
2315
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002316 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002317 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302320error:
Eric Laurent994a6932013-07-17 11:51:42 -07002321 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322 return ret;
2323}
2324
2325static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002329 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330 char value[256];
2331 struct str_parms *reply = str_parms_create();
2332 size_t i, j;
2333 int ret;
2334 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002335
2336 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002337 if (reply) {
2338 str_parms_destroy(reply);
2339 }
2340 if (query) {
2341 str_parms_destroy(query);
2342 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002343 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2344 return NULL;
2345 }
2346
Eric Laurent994a6932013-07-17 11:51:42 -07002347 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2349 if (ret >= 0) {
2350 value[0] = '\0';
2351 i = 0;
2352 while (out->supported_channel_masks[i] != 0) {
2353 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2354 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2355 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002356 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002358 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 first = false;
2360 break;
2361 }
2362 }
2363 i++;
2364 }
2365 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2366 str = str_parms_to_str(reply);
2367 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002368 voice_extn_out_get_parameters(out, query, reply);
2369 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002370 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002371 free(str);
2372 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002373 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002375
Alexy Joseph62142aa2015-11-16 15:10:34 -08002376
2377 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2378 if (ret >= 0) {
2379 value[0] = '\0';
2380 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2381 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302382 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002383 } else {
2384 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302385 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002386 }
2387 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002388 if (str)
2389 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002390 str = str_parms_to_str(reply);
2391 }
2392
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002393 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2394 if (ret >= 0) {
2395 value[0] = '\0';
2396 i = 0;
2397 first = true;
2398 while (out->supported_formats[i] != 0) {
2399 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2400 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2401 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002402 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002403 }
2404 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2405 first = false;
2406 break;
2407 }
2408 }
2409 i++;
2410 }
2411 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002412 if (str)
2413 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002414 str = str_parms_to_str(reply);
2415 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002416
2417 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2418 if (ret >= 0) {
2419 value[0] = '\0';
2420 i = 0;
2421 first = true;
2422 while (out->supported_sample_rates[i] != 0) {
2423 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2424 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2425 if (!first) {
2426 strlcat(value, "|", sizeof(value));
2427 }
2428 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2429 first = false;
2430 break;
2431 }
2432 }
2433 i++;
2434 }
2435 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2436 if (str)
2437 free(str);
2438 str = str_parms_to_str(reply);
2439 }
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 str_parms_destroy(query);
2442 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002443 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 return str;
2445}
2446
2447static uint32_t out_get_latency(const struct audio_stream_out *stream)
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002450 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451
Alexy Josephaa54c872014-12-03 02:46:47 -08002452 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002453 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002454 } else {
2455 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002457 }
2458
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302459 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002460 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461}
2462
2463static int out_set_volume(struct audio_stream_out *stream, float left,
2464 float right)
2465{
Eric Laurenta9024de2013-04-04 09:19:12 -07002466 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002467 int volume[2];
2468
Eric Laurenta9024de2013-04-04 09:19:12 -07002469 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2470 /* only take left channel into account: the API is for stereo anyway */
2471 out->muted = (left == 0.0f);
2472 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002473 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002474 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002475 /*
2476 * Set mute or umute on HDMI passthrough stream.
2477 * Only take left channel into account.
2478 * Mute is 0 and unmute 1
2479 */
2480 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2481 } else {
2482 char mixer_ctl_name[128];
2483 struct audio_device *adev = out->dev;
2484 struct mixer_ctl *ctl;
2485 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002486 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002488 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2489 "Compress Playback %d Volume", pcm_device_id);
2490 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2491 if (!ctl) {
2492 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2493 __func__, mixer_ctl_name);
2494 return -EINVAL;
2495 }
2496 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2497 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2498 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2499 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002501 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 return -ENOSYS;
2504}
2505
2506static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2507 size_t bytes)
2508{
2509 struct stream_out *out = (struct stream_out *)stream;
2510 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302511 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002512 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002514 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302515
Naresh Tanniru80659832014-06-04 18:17:56 +05302516 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002517
Ashish Jainbbce4322016-02-16 13:25:27 +05302518 if (is_offload_usecase(out->usecase)) {
2519 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302520 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2521 pthread_mutex_unlock(&out->lock);
2522 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302523 } else {
2524 /* increase written size during SSR to avoid mismatch
2525 * with the written frames count in AF
2526 */
2527 out->written += bytes / (out->config.channels * sizeof(short));
2528 ALOGD(" %s: sound card is not active/SSR state", __func__);
2529 ret= -EIO;
2530 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302531 }
2532 }
2533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002535 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002536 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002537 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2538 ret = voice_extn_compress_voip_start_output_stream(out);
2539 else
2540 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002541 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002542 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002544 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 goto exit;
2546 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002547
2548 if (last_known_cal_step != -1) {
2549 ALOGD("%s: retry previous failed cal level set", __func__);
2550 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2551 }
2552
vivek mehta446c3962015-09-14 10:57:35 -07002553 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002554 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556
Ashish Jain81eb2a82015-05-13 10:52:34 +05302557 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002558 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302559 adev->is_channel_status_set = true;
2560 }
2561
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002562 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002563 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002564 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002565 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002566 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2567 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302568 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2569 ALOGD("copl(%p):send next track params in gapless", out);
2570 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2571 out->send_next_track_params = false;
2572 out->is_compr_metadata_avail = false;
2573 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002574 }
2575
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302577 if (ret < 0)
2578 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302579 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002580 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302581 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302583 } else if (-ENETRESET == ret) {
2584 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2585 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2586 pthread_mutex_unlock(&out->lock);
2587 out_standby(&out->stream.common);
2588 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 }
Ashish Jain5106d362016-05-11 19:23:33 +05302590 if ( ret == (ssize_t)bytes && !out->non_blocking)
2591 out->written += bytes;
2592
Naresh Tanniru80659832014-06-04 18:17:56 +05302593 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002595 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 out->playback_started = 1;
2597 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002598
2599 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2600 popcount(out->channel_mask),
2601 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 }
2603 pthread_mutex_unlock(&out->lock);
2604 return ret;
2605 } else {
2606 if (out->pcm) {
2607 if (out->muted)
2608 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002609
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302610 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002611
2612 if (adev->adm_request_focus)
2613 adev->adm_request_focus(adev->adm_data, out->handle);
2614
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002615 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2616 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2617 else
2618 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002619
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302620 if (ret < 0)
2621 ret = -errno;
2622 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002623 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002624
2625 if (adev->adm_abandon_focus)
2626 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 }
2629
2630exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302631 /* ToDo: There may be a corner case when SSR happens back to back during
2632 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302634 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302635 }
2636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 pthread_mutex_unlock(&out->lock);
2638
2639 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002640 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002641 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302642 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302643 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302644 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302645 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302646 out->standby = true;
2647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302649 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302650 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 }
2652 return bytes;
2653}
2654
2655static int out_get_render_position(const struct audio_stream_out *stream,
2656 uint32_t *dsp_frames)
2657{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302659 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002660
2661 if (dsp_frames == NULL)
2662 return -EINVAL;
2663
2664 *dsp_frames = 0;
2665 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002666 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302667
2668 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2669 * this operation and adev_close_output_stream(where out gets reset).
2670 */
2671 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2672 *dsp_frames = get_actual_pcm_frames_rendered(out);
2673 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2674 return 0;
2675 }
2676
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002677 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302678 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302679 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302681 if (ret < 0)
2682 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302684 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002685 }
2686 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302687 if (-ENETRESET == ret) {
2688 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2689 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2690 return -EINVAL;
2691 } else if(ret < 0) {
2692 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2693 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302694 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2695 /*
2696 * Handle corner case where compress session is closed during SSR
2697 * and timestamp is queried
2698 */
2699 ALOGE(" ERROR: sound card not active, return error");
2700 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302701 } else {
2702 return 0;
2703 }
Zhou Song32a556e2015-05-05 10:46:56 +08002704 } else if (audio_is_linear_pcm(out->format)) {
2705 *dsp_frames = out->written;
2706 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 } else
2708 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709}
2710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002711static int out_add_audio_effect(const struct audio_stream *stream __unused,
2712 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713{
2714 return 0;
2715}
2716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002717static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2718 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719{
2720 return 0;
2721}
2722
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002723static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2724 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
2726 return -EINVAL;
2727}
2728
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002729static int out_get_presentation_position(const struct audio_stream_out *stream,
2730 uint64_t *frames, struct timespec *timestamp)
2731{
2732 struct stream_out *out = (struct stream_out *)stream;
2733 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002734 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002735
Ashish Jain5106d362016-05-11 19:23:33 +05302736 /* below piece of code is not guarded against any lock because audioFliner serializes
2737 * this operation and adev_close_output_stream( where out gets reset).
2738 */
2739 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2740 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2741 *frames = get_actual_pcm_frames_rendered(out);
2742 /* this is the best we can do */
2743 clock_gettime(CLOCK_MONOTONIC, timestamp);
2744 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2745 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2746 return 0;
2747 }
2748
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002749 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002750
Ashish Jain5106d362016-05-11 19:23:33 +05302751 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2752 ret = compress_get_tstamp(out->compr, &dsp_frames,
2753 &out->sample_rate);
2754 ALOGVV("%s rendered frames %ld sample_rate %d",
2755 __func__, dsp_frames, out->sample_rate);
2756 *frames = dsp_frames;
2757 if (ret < 0)
2758 ret = -errno;
2759 if (-ENETRESET == ret) {
2760 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2761 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2762 ret = -EINVAL;
2763 } else
2764 ret = 0;
2765 /* this is the best we can do */
2766 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002767 } else {
2768 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002769 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002770 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2771 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002772 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002773 // This adjustment accounts for buffering after app processor.
2774 // It is based on estimated DSP latency per use case, rather than exact.
2775 signed_frames -=
2776 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2777
Eric Laurent949a0892013-09-20 09:20:13 -07002778 // It would be unusual for this value to be negative, but check just in case ...
2779 if (signed_frames >= 0) {
2780 *frames = signed_frames;
2781 ret = 0;
2782 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002783 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302784 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2785 *frames = out->written;
2786 clock_gettime(CLOCK_MONOTONIC, timestamp);
2787 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002788 }
2789 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002790 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002791 return ret;
2792}
2793
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794static int out_set_callback(struct audio_stream_out *stream,
2795 stream_callback_t callback, void *cookie)
2796{
2797 struct stream_out *out = (struct stream_out *)stream;
2798
2799 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002800 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 out->offload_callback = callback;
2802 out->offload_cookie = cookie;
2803 pthread_mutex_unlock(&out->lock);
2804 return 0;
2805}
2806
2807static int out_pause(struct audio_stream_out* stream)
2808{
2809 struct stream_out *out = (struct stream_out *)stream;
2810 int status = -ENOSYS;
2811 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002812 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002813 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002814 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302816 struct audio_device *adev = out->dev;
2817 int snd_scard_state = get_snd_card_state(adev);
2818
2819 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2820 status = compress_pause(out->compr);
2821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002823
Mingming Yin21854652016-04-13 11:54:02 -07002824 if (audio_extn_passthru_is_active()) {
2825 ALOGV("offload use case, pause passthru");
2826 audio_extn_passthru_on_pause(out);
2827 }
2828
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302829 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002830 audio_extn_dts_notify_playback_state(out->usecase, 0,
2831 out->sample_rate, popcount(out->channel_mask),
2832 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 }
2834 pthread_mutex_unlock(&out->lock);
2835 }
2836 return status;
2837}
2838
2839static int out_resume(struct audio_stream_out* stream)
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842 int status = -ENOSYS;
2843 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002844 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002845 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002847 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002848 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302849 struct audio_device *adev = out->dev;
2850 int snd_scard_state = get_snd_card_state(adev);
2851
Mingming Yin21854652016-04-13 11:54:02 -07002852 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2853 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2854 pthread_mutex_lock(&out->dev->lock);
2855 ALOGV("offload resume, check and set hdmi backend again");
2856 check_and_set_hdmi_backend(out);
2857 pthread_mutex_unlock(&out->dev->lock);
2858 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302859 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002860 }
2861 if (!status) {
2862 out->offload_state = OFFLOAD_STATE_PLAYING;
2863 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302864 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002865 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2866 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002867 }
2868 pthread_mutex_unlock(&out->lock);
2869 }
2870 return status;
2871}
2872
2873static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2874{
2875 struct stream_out *out = (struct stream_out *)stream;
2876 int status = -ENOSYS;
2877 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002878 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002879 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2881 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2882 else
2883 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2884 pthread_mutex_unlock(&out->lock);
2885 }
2886 return status;
2887}
2888
2889static int out_flush(struct audio_stream_out* stream)
2890{
2891 struct stream_out *out = (struct stream_out *)stream;
2892 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002893 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002894 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002895 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302897 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002899 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 return 0;
2901 }
2902 return -ENOSYS;
2903}
2904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905/** audio_stream_in implementation **/
2906static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2907{
2908 struct stream_in *in = (struct stream_in *)stream;
2909
2910 return in->config.rate;
2911}
2912
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002913static int in_set_sample_rate(struct audio_stream *stream __unused,
2914 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915{
2916 return -ENOSYS;
2917}
2918
2919static size_t in_get_buffer_size(const struct audio_stream *stream)
2920{
2921 struct stream_in *in = (struct stream_in *)stream;
2922
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002923 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2924 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002925 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2926 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002927
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002928 return in->config.period_size *
2929 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930}
2931
2932static uint32_t in_get_channels(const struct audio_stream *stream)
2933{
2934 struct stream_in *in = (struct stream_in *)stream;
2935
2936 return in->channel_mask;
2937}
2938
2939static audio_format_t in_get_format(const struct audio_stream *stream)
2940{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002941 struct stream_in *in = (struct stream_in *)stream;
2942
2943 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944}
2945
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002946static int in_set_format(struct audio_stream *stream __unused,
2947 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948{
2949 return -ENOSYS;
2950}
2951
2952static int in_standby(struct audio_stream *stream)
2953{
2954 struct stream_in *in = (struct stream_in *)stream;
2955 struct audio_device *adev = in->dev;
2956 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302957 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2958 stream, in->usecase, use_case_table[in->usecase]);
2959
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002960 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2961 /* Ignore standby in case of voip call because the voip input
2962 * stream is closed in adev_close_input_stream()
2963 */
2964 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2965 return status;
2966 }
2967
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002968 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002969 if (!in->standby && in->is_st_session) {
2970 ALOGD("%s: sound trigger pcm stop lab", __func__);
2971 audio_extn_sound_trigger_stop_lab(in);
2972 in->standby = 1;
2973 }
2974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002976 if (adev->adm_deregister_stream)
2977 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2978
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002979 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002981 if (in->pcm) {
2982 pcm_close(in->pcm);
2983 in->pcm = NULL;
2984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002986 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 }
2988 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002989 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 return status;
2991}
2992
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002993static int in_dump(const struct audio_stream *stream __unused,
2994 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995{
2996 return 0;
2997}
2998
2999static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3000{
3001 struct stream_in *in = (struct stream_in *)stream;
3002 struct audio_device *adev = in->dev;
3003 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003005 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303007 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 parms = str_parms_create_str(kvpairs);
3009
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303010 if (!parms)
3011 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003012 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003013 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003014
3015 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3016 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 val = atoi(value);
3018 /* no audio source uses val == 0 */
3019 if ((in->source != val) && (val != 0)) {
3020 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003021 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3022 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3023 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003024 (in->config.rate == 8000 || in->config.rate == 16000 ||
3025 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003026 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003027 err = voice_extn_compress_voip_open_input_stream(in);
3028 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003029 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003030 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003031 }
3032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 }
3034 }
3035
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003036 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3037 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003039 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 in->device = val;
3041 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003042 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003043 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 }
3045 }
3046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003048 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049
3050 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303051error:
Eric Laurent994a6932013-07-17 11:51:42 -07003052 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 return ret;
3054}
3055
3056static char* in_get_parameters(const struct audio_stream *stream,
3057 const char *keys)
3058{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003059 struct stream_in *in = (struct stream_in *)stream;
3060 struct str_parms *query = str_parms_create_str(keys);
3061 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003062 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003063
3064 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003065 if (reply) {
3066 str_parms_destroy(reply);
3067 }
3068 if (query) {
3069 str_parms_destroy(query);
3070 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003071 ALOGE("in_get_parameters: failed to create query or reply");
3072 return NULL;
3073 }
3074
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 ALOGV("%s: enter: keys - %s", __func__, keys);
3076
3077 voice_extn_in_get_parameters(in, query, reply);
3078
3079 str = str_parms_to_str(reply);
3080 str_parms_destroy(query);
3081 str_parms_destroy(reply);
3082
3083 ALOGV("%s: exit: returns - %s", __func__, str);
3084 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085}
3086
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003087static int in_set_gain(struct audio_stream_in *stream __unused,
3088 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089{
3090 return 0;
3091}
3092
3093static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3094 size_t bytes)
3095{
3096 struct stream_in *in = (struct stream_in *)stream;
3097 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303098 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303099 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303100 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003102 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303103
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003104 if (in->is_st_session) {
3105 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3106 /* Read from sound trigger HAL */
3107 audio_extn_sound_trigger_read(in, buffer, bytes);
3108 pthread_mutex_unlock(&in->lock);
3109 return bytes;
3110 }
3111
Ashish Jainbbce4322016-02-16 13:25:27 +05303112 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003113 ALOGD(" %s: sound card is not active/SSR state", __func__);
3114 ret= -EIO;;
3115 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303116 }
3117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003119 pthread_mutex_lock(&adev->lock);
3120 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3121 ret = voice_extn_compress_voip_start_input_stream(in);
3122 else
3123 ret = start_input_stream(in);
3124 pthread_mutex_unlock(&adev->lock);
3125 if (ret != 0) {
3126 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 }
3128 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003129 if (adev->adm_register_input_stream)
3130 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003133 if (adev->adm_request_focus)
3134 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303137 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003138 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303139 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003140 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303141 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003142 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303143 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003144 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303145 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3146 if (bytes % 4 == 0) {
3147 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3148 int_buf_stream = buffer;
3149 for (size_t itt=0; itt < bytes/4 ; itt++) {
3150 int_buf_stream[itt] >>= 8;
3151 }
3152 } else {
3153 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3154 ret = -EINVAL;
3155 goto exit;
3156 }
3157 } if (ret < 0) {
3158 ret = -errno;
3159 }
3160 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 }
3162
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003163 if (adev->adm_abandon_focus)
3164 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 /*
3167 * Instead of writing zeroes here, we could trust the hardware
3168 * to always provide zeroes when muted.
3169 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303170 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3171 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 memset(buffer, 0, bytes);
3173
3174exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303175 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303176 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003177 if (-ENETRESET == ret)
3178 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 pthread_mutex_unlock(&in->lock);
3181
3182 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303183 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303184 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303185 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303186 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303187 in->standby = true;
3188 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303189 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003191 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303192 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303193 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 }
3195 return bytes;
3196}
3197
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003198static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199{
3200 return 0;
3201}
3202
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003203static int add_remove_audio_effect(const struct audio_stream *stream,
3204 effect_handle_t effect,
3205 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003207 struct stream_in *in = (struct stream_in *)stream;
3208 int status = 0;
3209 effect_descriptor_t desc;
3210
3211 status = (*effect)->get_descriptor(effect, &desc);
3212 if (status != 0)
3213 return status;
3214
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003215 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003216 pthread_mutex_lock(&in->dev->lock);
3217 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3218 in->enable_aec != enable &&
3219 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3220 in->enable_aec = enable;
3221 if (!in->standby)
3222 select_devices(in->dev, in->usecase);
3223 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003224 if (in->enable_ns != enable &&
3225 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3226 in->enable_ns = enable;
3227 if (!in->standby)
3228 select_devices(in->dev, in->usecase);
3229 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003230 pthread_mutex_unlock(&in->dev->lock);
3231 pthread_mutex_unlock(&in->lock);
3232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 return 0;
3234}
3235
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003236static int in_add_audio_effect(const struct audio_stream *stream,
3237 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238{
Eric Laurent994a6932013-07-17 11:51:42 -07003239 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003240 return add_remove_audio_effect(stream, effect, true);
3241}
3242
3243static int in_remove_audio_effect(const struct audio_stream *stream,
3244 effect_handle_t effect)
3245{
Eric Laurent994a6932013-07-17 11:51:42 -07003246 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003247 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
3250static int adev_open_output_stream(struct audio_hw_device *dev,
3251 audio_io_handle_t handle,
3252 audio_devices_t devices,
3253 audio_output_flags_t flags,
3254 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003255 struct audio_stream_out **stream_out,
3256 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257{
3258 struct audio_device *adev = (struct audio_device *)dev;
3259 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303260 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003261 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303264
3265 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3266 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003267 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303268 return -EINVAL;
3269 }
3270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3272
Mingming Yin3a941d42016-02-17 18:08:05 -08003273 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3274 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303275 devices, flags, &out->stream);
3276
3277
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003278 if (!out) {
3279 return -ENOMEM;
3280 }
3281
Haynes Mathew George204045b2015-02-25 20:32:03 -08003282 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003283 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003284 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 if (devices == AUDIO_DEVICE_NONE)
3287 devices = AUDIO_DEVICE_OUT_SPEAKER;
3288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 out->flags = flags;
3290 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003291 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003292 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003293 out->sample_rate = config->sample_rate;
3294 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3295 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003296 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003297 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003298 out->non_blocking = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299
Mingming Yin3a941d42016-02-17 18:08:05 -08003300 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3301 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3302 pthread_mutex_lock(&adev->lock);
3303 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3304 ret = read_hdmi_sink_caps(out);
3305 pthread_mutex_unlock(&adev->lock);
3306 if (ret != 0) {
3307 if (ret == -ENOSYS) {
3308 /* ignore and go with default */
3309 ret = 0;
3310 } else {
3311 ALOGE("error reading hdmi sink caps");
3312 goto error_open;
3313 }
3314 }
3315 }
3316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003318 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303319 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3320 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003321 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3322 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3323
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003324 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003325 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3326 /*
3327 * Do not handle stereo output in Multi-channel cases
3328 * Stereo case is handled in normal playback path
3329 */
3330 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3331 ret = AUDIO_CHANNEL_OUT_STEREO;
3332 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003333
3334 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3335 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003336 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003337 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003338 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003339
3340 if (config->sample_rate == 0)
3341 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3342 if (config->channel_mask == 0)
3343 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003344 if (config->format == 0)
3345 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003346
3347 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003349 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3351 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003353 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003355 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3356 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003357 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003358 ret = voice_extn_compress_voip_open_output_stream(out);
3359 if (ret != 0) {
3360 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3361 __func__, ret);
3362 goto error_open;
3363 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003364 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3365 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3368 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3369 ALOGE("%s: Unsupported Offload information", __func__);
3370 ret = -EINVAL;
3371 goto error_open;
3372 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003373
Mingming Yin3a941d42016-02-17 18:08:05 -08003374 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003375 if(config->offload_info.format == 0)
3376 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003377 if (config->offload_info.sample_rate == 0)
3378 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003379 }
3380
Mingming Yin90310102013-11-13 16:57:00 -08003381 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003382 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003383 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384 ret = -EINVAL;
3385 goto error_open;
3386 }
3387
3388 out->compr_config.codec = (struct snd_codec *)
3389 calloc(1, sizeof(struct snd_codec));
3390
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003391 if (!out->compr_config.codec) {
3392 ret = -ENOMEM;
3393 goto error_open;
3394 }
3395
vivek mehta0ea887a2015-08-26 14:01:20 -07003396 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303397 out->stream.pause = out_pause;
3398 out->stream.flush = out_flush;
3399 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003400 out->usecase = get_offload_usecase(adev, true);
3401 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003402 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003403 out->stream.set_callback = out_set_callback;
3404 out->stream.pause = out_pause;
3405 out->stream.resume = out_resume;
3406 out->stream.drain = out_drain;
3407 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003408 out->usecase = get_offload_usecase(adev, false);
3409 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003410 }
vivek mehta446c3962015-09-14 10:57:35 -07003411
3412 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003413 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3414 config->format == 0 && config->sample_rate == 0 &&
3415 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003416 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003417 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3418 } else {
3419 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3420 ret = -EEXIST;
3421 goto error_open;
3422 }
vivek mehta446c3962015-09-14 10:57:35 -07003423 }
3424
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003425 if (config->offload_info.channel_mask)
3426 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003427 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003428 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003429 config->offload_info.channel_mask = config->channel_mask;
3430 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003431 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 out->sample_rate = config->offload_info.sample_rate;
3433
Mingming Yin3ee55c62014-08-04 14:23:35 -07003434 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003436 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003437 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003438 audio_extn_dolby_get_snd_codec_id(adev, out,
3439 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003440 else
3441 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003442 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003443
Ashish Jain5106d362016-05-11 19:23:33 +05303444 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003445 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003446 platform_get_pcm_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303447 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
Mingming Yin21854652016-04-13 11:54:02 -07003448 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003449 out->compr_config.fragment_size =
3450 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303451 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003452 } else {
3453 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003454 platform_get_compress_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303455 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003456 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003458 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003459 out->compr_config.codec->bit_rate =
3460 config->offload_info.bit_rate;
3461 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003462 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303464 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003465 /*TODO: Do we need to change it for passthrough */
3466 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467
Manish Dewangana6fc5442015-08-24 20:30:31 +05303468 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3469 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3470 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3471 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
vivek mehta0ea887a2015-08-26 14:01:20 -07003472 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3473 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Ashish Jain5106d362016-05-11 19:23:33 +05303474 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
3475 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
3476 if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
Mingming Yin3ee55c62014-08-04 14:23:35 -07003477 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003478
Amit Shekhar6f461b12014-08-01 14:52:58 -07003479 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303480 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003481
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3483 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003484
Alexy Josephaa54c872014-12-03 02:46:47 -08003485
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003486 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303487 out->send_next_track_params = false;
3488 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003489 out->offload_state = OFFLOAD_STATE_IDLE;
3490 out->playback_started = 0;
3491
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003492 audio_extn_dts_create_state_notifier_node(out->usecase);
3493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003494 create_offload_callback_thread(out);
3495 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3496 __func__, config->offload_info.version,
3497 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303498
3499 /* Disable gapless if any of the following is true
3500 * passthrough playback
3501 * AV playback
3502 * Direct PCM playback
3503 */
3504 if (audio_extn_dolby_is_passthrough_stream(out) ||
3505 config->offload_info.has_video ||
3506 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3507 check_and_set_gapless_mode(adev, false);
3508 } else
3509 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003510
3511 if (audio_extn_dolby_is_passthrough_stream(out)) {
3512 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3513 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003514 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303515 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003516 if (ret != 0) {
3517 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3518 __func__, ret);
3519 goto error_open;
3520 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003521 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3522 if (config->sample_rate == 0)
3523 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3524 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3525 config->sample_rate != 8000) {
3526 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3527 ret = -EINVAL;
3528 goto error_open;
3529 }
3530 out->sample_rate = config->sample_rate;
3531 out->config.rate = config->sample_rate;
3532 if (config->format == AUDIO_FORMAT_DEFAULT)
3533 config->format = AUDIO_FORMAT_PCM_16_BIT;
3534 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3535 config->format = AUDIO_FORMAT_PCM_16_BIT;
3536 ret = -EINVAL;
3537 goto error_open;
3538 }
3539 out->format = config->format;
3540 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3541 out->config = pcm_config_afe_proxy_playback;
3542 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003543 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3544 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3545 out->config = pcm_config_low_latency;
3546 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003547 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003548 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3550 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003551 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003552 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3553 format = AUDIO_FORMAT_PCM_16_BIT;
3554 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3555 out->config = pcm_config_deep_buffer;
3556 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003557 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003558 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003559 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003560 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003561 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003562 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 }
3564
Mingming Yin21854652016-04-13 11:54:02 -07003565 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3566 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003567 /* TODO remove this hardcoding and check why width is zero*/
3568 if (out->bit_width == 0)
3569 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003570 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3571 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003572 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303573 out->bit_width, out->channel_mask,
3574 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003575 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3576 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3577 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003578 if(adev->primary_output == NULL)
3579 adev->primary_output = out;
3580 else {
3581 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003582 ret = -EEXIST;
3583 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003584 }
3585 }
3586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587 /* Check if this usecase is already existing */
3588 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003589 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3590 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003593 ret = -EEXIST;
3594 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 }
3596 pthread_mutex_unlock(&adev->lock);
3597
3598 out->stream.common.get_sample_rate = out_get_sample_rate;
3599 out->stream.common.set_sample_rate = out_set_sample_rate;
3600 out->stream.common.get_buffer_size = out_get_buffer_size;
3601 out->stream.common.get_channels = out_get_channels;
3602 out->stream.common.get_format = out_get_format;
3603 out->stream.common.set_format = out_set_format;
3604 out->stream.common.standby = out_standby;
3605 out->stream.common.dump = out_dump;
3606 out->stream.common.set_parameters = out_set_parameters;
3607 out->stream.common.get_parameters = out_get_parameters;
3608 out->stream.common.add_audio_effect = out_add_audio_effect;
3609 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3610 out->stream.get_latency = out_get_latency;
3611 out->stream.set_volume = out_set_volume;
3612 out->stream.write = out_write;
3613 out->stream.get_render_position = out_get_render_position;
3614 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003615 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003618 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003619 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
3621 config->format = out->stream.common.get_format(&out->stream.common);
3622 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3623 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3624
3625 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303626 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003627 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003628
3629 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3630 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3631 popcount(out->channel_mask), out->playback_started);
3632
Eric Laurent994a6932013-07-17 11:51:42 -07003633 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003635
3636error_open:
3637 free(out);
3638 *stream_out = NULL;
3639 ALOGD("%s: exit: ret %d", __func__, ret);
3640 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641}
3642
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003643static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 struct audio_stream_out *stream)
3645{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003646 struct stream_out *out = (struct stream_out *)stream;
3647 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003648 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003649
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303650 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3651
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003652 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303653 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003654 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303655 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003656 if(ret != 0)
3657 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3658 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003659 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003660 out_standby(&stream->common);
3661
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003662 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003663 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003665 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 if (out->compr_config.codec != NULL)
3667 free(out->compr_config.codec);
3668 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003669
3670 if (adev->voice_tx_output == out)
3671 adev->voice_tx_output = NULL;
3672
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 pthread_cond_destroy(&out->cond);
3674 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003676 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677}
3678
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003679static void close_compress_sessions(struct audio_device *adev)
3680{
Mingming Yin7b762e72015-03-04 13:47:32 -08003681 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303682 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003683 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003684 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303685
3686 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003687 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303688 if (is_offload_usecase(usecase->id)) {
3689 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003690 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3691 out = usecase->stream.out;
3692 pthread_mutex_unlock(&adev->lock);
3693 out_standby(&out->stream.common);
3694 pthread_mutex_lock(&adev->lock);
3695 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303696 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003697 }
3698 pthread_mutex_unlock(&adev->lock);
3699}
3700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3702{
3703 struct audio_device *adev = (struct audio_device *)dev;
3704 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003706 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003707 int ret;
3708 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003710 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303713 if (!parms)
3714 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003715 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3716 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303717 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303718 if (strstr(snd_card_status, "OFFLINE")) {
3719 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303720 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003721 //close compress sessions on OFFLINE status
3722 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303723 } else if (strstr(snd_card_status, "ONLINE")) {
3724 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303725 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003726 //send dts hpx license if enabled
3727 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303728 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303729 }
3730
3731 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003732 status = voice_set_parameters(adev, parms);
3733 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003734 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003736 status = platform_set_parameters(adev->platform, parms);
3737 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003738 goto done;
3739
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003740 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3741 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003742 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3744 adev->bluetooth_nrec = true;
3745 else
3746 adev->bluetooth_nrec = false;
3747 }
3748
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003749 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3750 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3752 adev->screen_off = false;
3753 else
3754 adev->screen_off = true;
3755 }
3756
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003757 ret = str_parms_get_int(parms, "rotation", &val);
3758 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003759 bool reverse_speakers = false;
3760 switch(val) {
3761 // FIXME: note that the code below assumes that the speakers are in the correct placement
3762 // relative to the user when the device is rotated 90deg from its default rotation. This
3763 // assumption is device-specific, not platform-specific like this code.
3764 case 270:
3765 reverse_speakers = true;
3766 break;
3767 case 0:
3768 case 90:
3769 case 180:
3770 break;
3771 default:
3772 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003773 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003774 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003775 if (status == 0) {
3776 if (adev->speaker_lr_swap != reverse_speakers) {
3777 adev->speaker_lr_swap = reverse_speakers;
3778 // only update the selected device if there is active pcm playback
3779 struct audio_usecase *usecase;
3780 struct listnode *node;
3781 list_for_each(node, &adev->usecase_list) {
3782 usecase = node_to_item(node, struct audio_usecase, list);
3783 if (usecase->type == PCM_PLAYBACK) {
3784 select_devices(adev, usecase->id);
3785 break;
3786 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003787 }
3788 }
3789 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003790 }
3791
Mingming Yin514a8bc2014-07-29 15:22:21 -07003792 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3793 if (ret >= 0) {
3794 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3795 adev->bt_wb_speech_enabled = true;
3796 else
3797 adev->bt_wb_speech_enabled = false;
3798 }
3799
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003800 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3801 if (ret >= 0) {
3802 val = atoi(value);
3803 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3804 ALOGV("cache new edid");
3805 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003806 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3807 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07003808 /*
3809 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3810 * Per AudioPolicyManager, USB device is higher priority than WFD.
3811 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3812 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3813 * starting voice call on USB
3814 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003815 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3816 if (ret >= 0) {
3817 audio_extn_usb_add_device(val, atoi(value));
3818 }
vivek mehta344576a2016-04-12 18:56:03 -07003819 ALOGV("detected USB connect .. disable proxy");
3820 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003821 }
3822 }
3823
3824 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3825 if (ret >= 0) {
3826 val = atoi(value);
3827 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3828 ALOGV("invalidate cached edid");
3829 platform_invalidate_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003830 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3831 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
3832 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3833 if (ret >= 0) {
3834 audio_extn_usb_remove_device(val, atoi(value));
3835 }
vivek mehta344576a2016-04-12 18:56:03 -07003836 ALOGV("detected USB disconnect .. enable proxy");
3837 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003838 }
3839 }
3840
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003841 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003842
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003843done:
3844 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003845 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303846error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003847 ALOGV("%s: exit with code(%d)", __func__, status);
3848 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849}
3850
3851static char* adev_get_parameters(const struct audio_hw_device *dev,
3852 const char *keys)
3853{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003854 struct audio_device *adev = (struct audio_device *)dev;
3855 struct str_parms *reply = str_parms_create();
3856 struct str_parms *query = str_parms_create_str(keys);
3857 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303858 char value[256] = {0};
3859 int ret = 0;
3860
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003861 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003862 if (reply) {
3863 str_parms_destroy(reply);
3864 }
3865 if (query) {
3866 str_parms_destroy(query);
3867 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003868 ALOGE("adev_get_parameters: failed to create query or reply");
3869 return NULL;
3870 }
3871
Naresh Tannirud7205b62014-06-20 02:54:48 +05303872 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3873 sizeof(value));
3874 if (ret >=0) {
3875 int val = 1;
3876 pthread_mutex_lock(&adev->snd_card_status.lock);
3877 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3878 val = 0;
3879 pthread_mutex_unlock(&adev->snd_card_status.lock);
3880 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3881 goto exit;
3882 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003883
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003884 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003885 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003886 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003887 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303888 pthread_mutex_unlock(&adev->lock);
3889
Naresh Tannirud7205b62014-06-20 02:54:48 +05303890exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003891 str = str_parms_to_str(reply);
3892 str_parms_destroy(query);
3893 str_parms_destroy(reply);
3894
3895 ALOGV("%s: exit: returns - %s", __func__, str);
3896 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897}
3898
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003899static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900{
3901 return 0;
3902}
3903
3904static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3905{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003906 int ret;
3907 struct audio_device *adev = (struct audio_device *)dev;
3908 pthread_mutex_lock(&adev->lock);
3909 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003910 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003911 pthread_mutex_unlock(&adev->lock);
3912 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913}
3914
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003915static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3916 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917{
3918 return -ENOSYS;
3919}
3920
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003921static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3922 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923{
3924 return -ENOSYS;
3925}
3926
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003927static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3928 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929{
3930 return -ENOSYS;
3931}
3932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003933static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3934 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935{
3936 return -ENOSYS;
3937}
3938
3939static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3940{
3941 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943 pthread_mutex_lock(&adev->lock);
3944 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003945 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003947 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003948 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003949 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003950 adev->current_call_output = NULL;
3951 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 }
3953 pthread_mutex_unlock(&adev->lock);
3954 return 0;
3955}
3956
3957static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3958{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003959 int ret;
3960
3961 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003962 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003963 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3964 pthread_mutex_unlock(&adev->lock);
3965
3966 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967}
3968
3969static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3970{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003971 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 return 0;
3973}
3974
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003975static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 const struct audio_config *config)
3977{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003978 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003980 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3981 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982}
3983
3984static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003985 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 audio_devices_t devices,
3987 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003988 struct audio_stream_in **stream_in,
3989 audio_input_flags_t flags __unused,
3990 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003991 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992{
3993 struct audio_device *adev = (struct audio_device *)dev;
3994 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003995 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003996 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003997 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304000 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4001 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304003 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004
4005 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004006
4007 if (!in) {
4008 ALOGE("failed to allocate input stream");
4009 return -ENOMEM;
4010 }
4011
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304012 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304013 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4014 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004015 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004016 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004018 in->stream.common.get_sample_rate = in_get_sample_rate;
4019 in->stream.common.set_sample_rate = in_set_sample_rate;
4020 in->stream.common.get_buffer_size = in_get_buffer_size;
4021 in->stream.common.get_channels = in_get_channels;
4022 in->stream.common.get_format = in_get_format;
4023 in->stream.common.set_format = in_set_format;
4024 in->stream.common.standby = in_standby;
4025 in->stream.common.dump = in_dump;
4026 in->stream.common.set_parameters = in_set_parameters;
4027 in->stream.common.get_parameters = in_get_parameters;
4028 in->stream.common.add_audio_effect = in_add_audio_effect;
4029 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4030 in->stream.set_gain = in_set_gain;
4031 in->stream.read = in_read;
4032 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4033
4034 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004035 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 in->standby = 1;
4038 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004039 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004040 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041
4042 /* Update config params with the requested sample rate and channels */
4043 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004044 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4045 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4046 is_low_latency = true;
4047#if LOW_LATENCY_CAPTURE_USE_CASE
4048 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4049#endif
4050 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004053 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304054 in->bit_width = 16;
4055 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004057 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304058 if (adev->mode != AUDIO_MODE_IN_CALL) {
4059 ret = -EINVAL;
4060 goto err_open;
4061 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004062 if (config->sample_rate == 0)
4063 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4064 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4065 config->sample_rate != 8000) {
4066 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4067 ret = -EINVAL;
4068 goto err_open;
4069 }
4070 if (config->format == AUDIO_FORMAT_DEFAULT)
4071 config->format = AUDIO_FORMAT_PCM_16_BIT;
4072 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4073 config->format = AUDIO_FORMAT_PCM_16_BIT;
4074 ret = -EINVAL;
4075 goto err_open;
4076 }
4077
4078 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4079 in->config = pcm_config_afe_proxy_record;
4080 in->config.channels = channel_count;
4081 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304082 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304083 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4084 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004085 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004086 audio_extn_compr_cap_format_supported(config->format) &&
4087 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004088 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004089 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304090 /* restrict 24 bit capture for unprocessed source only
4091 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4092 */
4093 if (config->format == AUDIO_FORMAT_DEFAULT) {
4094 config->format = AUDIO_FORMAT_PCM_16_BIT;
4095 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4096 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4097 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4098 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4099 bool ret_error = false;
4100 in->bit_width = 24;
4101 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4102 from HAL is 24_packed and 8_24
4103 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4104 24_packed return error indicating supported format is 24_packed
4105 *> In case of any other source requesting 24 bit or float return error
4106 indicating format supported is 16 bit only.
4107
4108 on error flinger will retry with supported format passed
4109 */
4110 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4111 (source != AUDIO_SOURCE_CAMCORDER)) {
4112 config->format = AUDIO_FORMAT_PCM_16_BIT;
4113 if( config->sample_rate > 48000)
4114 config->sample_rate = 48000;
4115 ret_error = true;
4116 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4117 in->config.format = PCM_FORMAT_S24_3LE;
4118 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4119 in->config.format = PCM_FORMAT_S24_LE;
4120 } else {
4121 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4122 ret_error = true;
4123 }
4124
4125 if (ret_error) {
4126 ret = -EINVAL;
4127 goto err_open;
4128 }
4129 }
4130
4131 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004132 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004133 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004134 buffer_size = get_input_buffer_size(config->sample_rate,
4135 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004136 channel_count,
4137 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004138 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004139 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4140 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4141 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004142 (in->config.rate == 8000 || in->config.rate == 16000 ||
4143 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004144 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4145 voice_extn_compress_voip_open_input_stream(in);
4146 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004147 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004149 /* This stream could be for sound trigger lab,
4150 get sound trigger pcm if present */
4151 audio_extn_sound_trigger_check_and_get_session(in);
4152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004154 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004155 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156
4157err_open:
4158 free(in);
4159 *stream_in = NULL;
4160 return ret;
4161}
4162
4163static void adev_close_input_stream(struct audio_hw_device *dev,
4164 struct audio_stream_in *stream)
4165{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004166 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004167 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004168 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304169
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304170 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004171
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304172 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004173 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304174
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004175 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304176 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004177 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304178 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004179 if (ret != 0)
4180 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4181 __func__, ret);
4182 } else
4183 in_standby(&stream->common);
4184
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004185 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004186 audio_extn_ssr_deinit();
4187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188
Mingming Yine62d7842013-10-25 16:26:03 -07004189 if(audio_extn_compr_cap_enabled() &&
4190 audio_extn_compr_cap_format_supported(in->config.format))
4191 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004192
Mingming Yinfd7607b2016-01-22 12:48:44 -08004193 if (in->is_st_session) {
4194 ALOGV("%s: sound trigger pcm stop lab", __func__);
4195 audio_extn_sound_trigger_stop_lab(in);
4196 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004197 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 return;
4199}
4200
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004201static int adev_dump(const audio_hw_device_t *device __unused,
4202 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203{
4204 return 0;
4205}
4206
4207static int adev_close(hw_device_t *device)
4208{
4209 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004210
4211 if (!adev)
4212 return 0;
4213
4214 pthread_mutex_lock(&adev_init_lock);
4215
4216 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004217 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004218 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004219 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004220 audio_route_free(adev->audio_route);
4221 free(adev->snd_dev_ref_cnt);
4222 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004223 if (adev->adm_deinit)
4224 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004225 free(device);
4226 adev = NULL;
4227 }
4228 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230 return 0;
4231}
4232
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004233/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4234 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4235 * just that it _might_ work.
4236 */
4237static int period_size_is_plausible_for_low_latency(int period_size)
4238{
4239 switch (period_size) {
4240 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004241 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004242 case 240:
4243 case 320:
4244 case 480:
4245 return 1;
4246 default:
4247 return 0;
4248 }
4249}
4250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251static int adev_open(const hw_module_t *module, const char *name,
4252 hw_device_t **device)
4253{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004254 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4256
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004257 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004258 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004259 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004260 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004261 ALOGD("%s: returning existing instance of adev", __func__);
4262 ALOGD("%s: exit", __func__);
4263 pthread_mutex_unlock(&adev_init_lock);
4264 return 0;
4265 }
4266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 adev = calloc(1, sizeof(struct audio_device));
4268
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004269 if (!adev) {
4270 pthread_mutex_unlock(&adev_init_lock);
4271 return -ENOMEM;
4272 }
4273
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004274 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4277 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4278 adev->device.common.module = (struct hw_module_t *)module;
4279 adev->device.common.close = adev_close;
4280
4281 adev->device.init_check = adev_init_check;
4282 adev->device.set_voice_volume = adev_set_voice_volume;
4283 adev->device.set_master_volume = adev_set_master_volume;
4284 adev->device.get_master_volume = adev_get_master_volume;
4285 adev->device.set_master_mute = adev_set_master_mute;
4286 adev->device.get_master_mute = adev_get_master_mute;
4287 adev->device.set_mode = adev_set_mode;
4288 adev->device.set_mic_mute = adev_set_mic_mute;
4289 adev->device.get_mic_mute = adev_get_mic_mute;
4290 adev->device.set_parameters = adev_set_parameters;
4291 adev->device.get_parameters = adev_get_parameters;
4292 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4293 adev->device.open_output_stream = adev_open_output_stream;
4294 adev->device.close_output_stream = adev_close_output_stream;
4295 adev->device.open_input_stream = adev_open_input_stream;
4296 adev->device.close_input_stream = adev_close_input_stream;
4297 adev->device.dump = adev_dump;
4298
4299 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004301 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004302 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004305 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004306 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004307 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004308 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004309 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004310 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004311 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004312 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304313 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304314 adev->perf_lock_opts[0] = 0x101;
4315 adev->perf_lock_opts[1] = 0x20E;
4316 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304317
4318 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4319 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004321 adev->platform = platform_init(adev);
4322 if (!adev->platform) {
4323 free(adev->snd_dev_ref_cnt);
4324 free(adev);
4325 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4326 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004327 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004328 return -EINVAL;
4329 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004330
Naresh Tanniru4c630392014-05-12 01:05:52 +05304331 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4332
Eric Laurentc4aef752013-09-12 17:45:53 -07004333 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4334 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4335 if (adev->visualizer_lib == NULL) {
4336 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4337 } else {
4338 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4339 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004340 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004341 "visualizer_hal_start_output");
4342 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004343 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004344 "visualizer_hal_stop_output");
4345 }
4346 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004347 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004348 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004349
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004350 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4351 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4352 if (adev->offload_effects_lib == NULL) {
4353 ALOGE("%s: DLOPEN failed for %s", __func__,
4354 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4355 } else {
4356 ALOGV("%s: DLOPEN successful for %s", __func__,
4357 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4358 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304359 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004360 "offload_effects_bundle_hal_start_output");
4361 adev->offload_effects_stop_output =
4362 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4363 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004364 adev->offload_effects_set_hpx_state =
4365 (int (*)(bool))dlsym(adev->offload_effects_lib,
4366 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304367 adev->offload_effects_get_parameters =
4368 (void (*)(struct str_parms *, struct str_parms *))
4369 dlsym(adev->offload_effects_lib,
4370 "offload_effects_bundle_get_parameters");
4371 adev->offload_effects_set_parameters =
4372 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4373 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004374 }
4375 }
4376
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004377 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4378 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4379 if (adev->adm_lib == NULL) {
4380 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4381 } else {
4382 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4383 adev->adm_init = (adm_init_t)
4384 dlsym(adev->adm_lib, "adm_init");
4385 adev->adm_deinit = (adm_deinit_t)
4386 dlsym(adev->adm_lib, "adm_deinit");
4387 adev->adm_register_input_stream = (adm_register_input_stream_t)
4388 dlsym(adev->adm_lib, "adm_register_input_stream");
4389 adev->adm_register_output_stream = (adm_register_output_stream_t)
4390 dlsym(adev->adm_lib, "adm_register_output_stream");
4391 adev->adm_deregister_stream = (adm_deregister_stream_t)
4392 dlsym(adev->adm_lib, "adm_deregister_stream");
4393 adev->adm_request_focus = (adm_request_focus_t)
4394 dlsym(adev->adm_lib, "adm_request_focus");
4395 adev->adm_abandon_focus = (adm_abandon_focus_t)
4396 dlsym(adev->adm_lib, "adm_abandon_focus");
4397 }
4398 }
4399
Mingming Yin514a8bc2014-07-29 15:22:21 -07004400 adev->bt_wb_speech_enabled = false;
4401
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004402 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 *device = &adev->device.common;
4404
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004405 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4406 &adev->streams_output_cfg_list);
4407
Kiran Kandi910e1862013-10-29 13:29:42 -07004408 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004409
4410 char value[PROPERTY_VALUE_MAX];
4411 int trial;
4412 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4413 trial = atoi(value);
4414 if (period_size_is_plausible_for_low_latency(trial)) {
4415 pcm_config_low_latency.period_size = trial;
4416 pcm_config_low_latency.start_threshold = trial / 4;
4417 pcm_config_low_latency.avail_min = trial / 4;
4418 configured_low_latency_capture_period_size = trial;
4419 }
4420 }
4421 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4422 trial = atoi(value);
4423 if (period_size_is_plausible_for_low_latency(trial)) {
4424 configured_low_latency_capture_period_size = trial;
4425 }
4426 }
4427
vivek mehta446c3962015-09-14 10:57:35 -07004428 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004429 pthread_mutex_unlock(&adev_init_lock);
4430
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004431 if (adev->adm_init)
4432 adev->adm_data = adev->adm_init();
4433
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304434 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004435 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436 return 0;
4437}
4438
4439static struct hw_module_methods_t hal_module_methods = {
4440 .open = adev_open,
4441};
4442
4443struct audio_module HAL_MODULE_INFO_SYM = {
4444 .common = {
4445 .tag = HARDWARE_MODULE_TAG,
4446 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4447 .hal_api_version = HARDWARE_HAL_API_VERSION,
4448 .id = AUDIO_HARDWARE_MODULE_ID,
4449 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004450 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451 .methods = &hal_module_methods,
4452 },
4453};