blob: 55b0cc758c7e5e6d799ef15829090557c0bcd74b [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__);
1497 pthread_cond_signal(&out->cond);
1498 continue;
1499 }
1500 out->offload_thread_blocked = true;
1501 pthread_mutex_unlock(&out->lock);
1502 send_callback = false;
1503 switch(cmd->cmd) {
1504 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001505 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001506 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001507 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001508 send_callback = true;
1509 event = STREAM_CBK_EVENT_WRITE_READY;
1510 break;
1511 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001512 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301513 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001514 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301515 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001516 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301517 if (ret < 0)
1518 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301519 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301520 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001521 compress_drain(out->compr);
1522 else
1523 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301524 if (ret != -ENETRESET) {
1525 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301526 pthread_mutex_lock(&out->lock);
1527 out->send_new_metadata = 1;
1528 out->send_next_track_params = true;
1529 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301530 event = STREAM_CBK_EVENT_DRAIN_READY;
1531 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1532 } else
1533 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 break;
1535 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001536 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001537 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001538 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001539 send_callback = true;
1540 event = STREAM_CBK_EVENT_DRAIN_READY;
1541 break;
1542 default:
1543 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1544 break;
1545 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001546 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 out->offload_thread_blocked = false;
1548 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001549 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001550 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001551 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001552 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001553 free(cmd);
1554 }
1555
1556 pthread_cond_signal(&out->cond);
1557 while (!list_empty(&out->offload_cmd_list)) {
1558 item = list_head(&out->offload_cmd_list);
1559 list_remove(item);
1560 free(node_to_item(item, struct offload_cmd, node));
1561 }
1562 pthread_mutex_unlock(&out->lock);
1563
1564 return NULL;
1565}
1566
1567static int create_offload_callback_thread(struct stream_out *out)
1568{
1569 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1570 list_init(&out->offload_cmd_list);
1571 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1572 offload_thread_loop, out);
1573 return 0;
1574}
1575
1576static int destroy_offload_callback_thread(struct stream_out *out)
1577{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001578 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001579 stop_compressed_output_l(out);
1580 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1581
1582 pthread_mutex_unlock(&out->lock);
1583 pthread_join(out->offload_thread, (void **) NULL);
1584 pthread_cond_destroy(&out->offload_cond);
1585
1586 return 0;
1587}
1588
Mingming Yin21854652016-04-13 11:54:02 -07001589static bool allow_hdmi_channel_config(struct audio_device *adev,
1590 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001591{
1592 struct listnode *node;
1593 struct audio_usecase *usecase;
1594 bool ret = true;
1595
Mingming Yin21854652016-04-13 11:54:02 -07001596 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1597 ret = false;
1598 goto exit;
1599 }
1600
1601 if (audio_extn_passthru_is_active()) {
1602 ALOGI("%s: Compress audio passthrough is active,"
1603 "no HDMI config change allowed", __func__);
1604 ret = false;
1605 goto exit;
1606 }
1607
Eric Laurent07eeafd2013-10-06 12:52:49 -07001608 list_for_each(node, &adev->usecase_list) {
1609 usecase = node_to_item(node, struct audio_usecase, list);
1610 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1611 /*
1612 * If voice call is already existing, do not proceed further to avoid
1613 * disabling/enabling both RX and TX devices, CSD calls, etc.
1614 * Once the voice call done, the HDMI channels can be configured to
1615 * max channels of remaining use cases.
1616 */
1617 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001618 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001619 __func__);
1620 ret = false;
1621 break;
1622 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001623 if (!enable_passthru) {
1624 ALOGV("%s: multi channel playback is active, "
1625 "no change in HDMI channels", __func__);
1626 ret = false;
1627 break;
1628 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001629 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001630 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001631 if (!enable_passthru) {
1632 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1633 ", no change in HDMI channels", __func__,
1634 usecase->stream.out->channel_mask);
1635 ret = false;
1636 break;
1637 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001638 }
1639 }
1640 }
Mingming Yin21854652016-04-13 11:54:02 -07001641 ALOGV("allow hdmi config %d", ret);
1642exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001643 return ret;
1644}
1645
Mingming Yin21854652016-04-13 11:54:02 -07001646static int check_and_set_hdmi_config(struct audio_device *adev,
1647 uint32_t channels,
1648 uint32_t sample_rate,
1649 audio_format_t format,
1650 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001651{
1652 struct listnode *node;
1653 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001654 int32_t factor = 1;
1655 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656
Mingming Yin21854652016-04-13 11:54:02 -07001657 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1658 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001659
Mingming Yin21854652016-04-13 11:54:02 -07001660 if (channels != adev->cur_hdmi_channels) {
1661 ALOGV("channel does not match current hdmi channels");
1662 config = true;
1663 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001664
Mingming Yin21854652016-04-13 11:54:02 -07001665 if (sample_rate != adev->cur_hdmi_sample_rate) {
1666 ALOGV("sample rate does not match current hdmi sample rate");
1667 config = true;
1668 }
1669
1670 if (format != adev->cur_hdmi_format) {
1671 ALOGV("format does not match current hdmi format");
1672 config = true;
1673 }
1674
1675 /* TBD - add check for bit width */
1676 if (!config) {
1677 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001678 return 0;
1679 }
1680
Mingming Yin21854652016-04-13 11:54:02 -07001681 if (enable_passthru &&
1682 (format == AUDIO_FORMAT_E_AC3)) {
1683 ALOGV("factor 4 for E_AC3 passthru");
1684 factor = 4;
1685 }
1686
1687 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1688 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001689 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001690 adev->cur_hdmi_format = format;
1691 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001692
1693 /*
1694 * Deroute all the playback streams routed to HDMI so that
1695 * the back end is deactivated. Note that backend will not
1696 * be deactivated if any one stream is connected to it.
1697 */
1698 list_for_each(node, &adev->usecase_list) {
1699 usecase = node_to_item(node, struct audio_usecase, list);
1700 if (usecase->type == PCM_PLAYBACK &&
1701 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001702 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001703 }
1704 }
1705
Mingming Yin21854652016-04-13 11:54:02 -07001706 bool was_active = audio_extn_keep_alive_is_active();
1707 if (was_active)
1708 audio_extn_keep_alive_stop();
1709
Eric Laurent07eeafd2013-10-06 12:52:49 -07001710 /*
1711 * Enable all the streams disabled above. Now the HDMI backend
1712 * will be activated with new channel configuration
1713 */
1714 list_for_each(node, &adev->usecase_list) {
1715 usecase = node_to_item(node, struct audio_usecase, list);
1716 if (usecase->type == PCM_PLAYBACK &&
1717 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001718 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001719 }
1720 }
1721
Mingming Yin21854652016-04-13 11:54:02 -07001722 if (was_active)
1723 audio_extn_keep_alive_start();
1724
Eric Laurent07eeafd2013-10-06 12:52:49 -07001725 return 0;
1726}
1727
Mingming Yin21854652016-04-13 11:54:02 -07001728/* called with out lock taken */
1729static int check_and_set_hdmi_backend(struct stream_out *out)
1730{
1731 struct audio_device *adev = out->dev;
1732 int ret;
1733 bool enable_passthru = false;
1734
1735 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1736 return -1;
1737
1738 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1739
1740 if (is_offload_usecase(out->usecase) &&
1741 audio_extn_dolby_is_passthrough_stream(out)) {
1742 enable_passthru = true;
1743 }
1744
1745 /* Check if change in HDMI channel config is allowed */
1746 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1747 return -EPERM;
1748 }
1749
1750 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1751 uint32_t channels;
1752 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1753
1754 if (enable_passthru) {
1755 audio_extn_passthru_on_start(out);
1756 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1757 }
1758
1759 /* For pass through case, the backend should be configured as stereo */
1760 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1761 out->compr_config.codec->ch_in;
1762
1763 ret = check_and_set_hdmi_config(adev, channels,
1764 out->sample_rate, out->format,
1765 enable_passthru);
1766 } else
1767 ret = check_and_set_hdmi_config(adev, out->config.channels,
1768 out->config.rate,
1769 out->format,
1770 false);
1771 return ret;
1772}
1773
1774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775static int stop_output_stream(struct stream_out *out)
1776{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301777 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 struct audio_usecase *uc_info;
1779 struct audio_device *adev = out->dev;
1780
Eric Laurent994a6932013-07-17 11:51:42 -07001781 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001782 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 uc_info = get_usecase_from_list(adev, out->usecase);
1784 if (uc_info == NULL) {
1785 ALOGE("%s: Could not find the usecase (%d) in the list",
1786 __func__, out->usecase);
1787 return -EINVAL;
1788 }
1789
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001790 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001791 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001792 if (adev->visualizer_stop_output != NULL)
1793 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001794
1795 audio_extn_dts_remove_state_notifier_node(out->usecase);
1796
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001797 if (adev->offload_effects_stop_output != NULL)
1798 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1799 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001800
Eric Laurent150dbfe2013-02-27 14:31:02 -08001801 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001802 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803
1804 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001805 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001807 list_remove(&uc_info->list);
1808 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001810 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001811 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001812 ALOGV("Disable passthrough , reset mixer to pcm");
1813 /* NO_PASSTHROUGH */
1814 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001815
1816 /* Must be called after removing the usecase from list */
1817 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1818 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1819 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1820 DEFAULT_HDMI_OUT_FORMAT,
1821 false);
1822 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001823 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1824 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001825
Eric Laurent994a6932013-07-17 11:51:42 -07001826 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 return ret;
1828}
1829
1830int start_output_stream(struct stream_out *out)
1831{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 struct audio_usecase *uc_info;
1834 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301835 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001837 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1838 ret = -EINVAL;
1839 goto error_config;
1840 }
1841
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301842 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1843 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1844 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301845
Naresh Tanniru80659832014-06-04 18:17:56 +05301846 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301847 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301848 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301849 goto error_config;
1850 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301851
Eric Laurentb23d5282013-05-14 15:27:20 -07001852 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853 if (out->pcm_device_id < 0) {
1854 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1855 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001856 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001857 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 }
1859
1860 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001861
1862 if (!uc_info) {
1863 ret = -ENOMEM;
1864 goto error_config;
1865 }
1866
Mingming Yin21854652016-04-13 11:54:02 -07001867 /* This must be called before adding this usecase to the list */
1868 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1869 /* This call can fail if compress pass thru is already active */
1870 check_and_set_hdmi_backend(out);
1871 }
1872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873 uc_info->id = out->usecase;
1874 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001875 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 uc_info->devices = out->devices;
1877 uc_info->in_snd_device = SND_DEVICE_NONE;
1878 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001879 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301881 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1882 adev->perf_lock_opts,
1883 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001884 select_devices(adev, out->usecase);
1885
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001886 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1887 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001888 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001889 unsigned int flags = PCM_OUT;
1890 unsigned int pcm_open_retry_count = 0;
1891 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1892 flags |= PCM_MMAP | PCM_NOIRQ;
1893 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1894 } else
1895 flags |= PCM_MONOTONIC;
1896
1897 while (1) {
1898 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1899 flags, &out->config);
1900 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1901 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1902 if (out->pcm != NULL) {
1903 pcm_close(out->pcm);
1904 out->pcm = NULL;
1905 }
1906 if (pcm_open_retry_count-- == 0) {
1907 ret = -EIO;
1908 goto error_open;
1909 }
1910 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1911 continue;
1912 }
1913 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001914 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001915
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001916 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1917 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001918
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001919 ALOGV("%s: pcm_prepare", __func__);
1920 if (pcm_is_ready(out->pcm)) {
1921 ret = pcm_prepare(out->pcm);
1922 if (ret < 0) {
1923 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1924 pcm_close(out->pcm);
1925 out->pcm = NULL;
1926 goto error_open;
1927 }
1928 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001930 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1931 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001933 out->compr = compress_open(adev->snd_card,
1934 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001935 COMPRESS_IN, &out->compr_config);
1936 if (out->compr && !is_compress_ready(out->compr)) {
1937 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1938 compress_close(out->compr);
1939 out->compr = NULL;
1940 ret = -EIO;
1941 goto error_open;
1942 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301943 /* compress_open sends params of the track, so reset the flag here */
1944 out->is_compr_metadata_avail = false;
1945
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 if (out->offload_callback)
1947 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001948
Fred Oh3f43e742015-03-04 18:42:34 -08001949 /* Since small bufs uses blocking writes, a write will be blocked
1950 for the default max poll time (20s) in the event of an SSR.
1951 Reduce the poll time to observe and deal with SSR faster.
1952 */
Ashish Jain5106d362016-05-11 19:23:33 +05301953 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001954 compress_set_max_poll_wait(out->compr, 1000);
1955 }
1956
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001957 audio_extn_dts_create_state_notifier_node(out->usecase);
1958 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1959 popcount(out->channel_mask),
1960 out->playback_started);
1961
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001962#ifdef DS1_DOLBY_DDP_ENABLED
1963 if (audio_extn_is_dolby_format(out->format))
1964 audio_extn_dolby_send_ddp_endp_params(adev);
1965#endif
Mingming Yin21854652016-04-13 11:54:02 -07001966 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001967 if (adev->visualizer_start_output != NULL)
1968 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1969 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301970 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001971 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301974 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001975 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001978error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301979 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001981error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301982 /*
1983 * sleep 50ms to allow sufficient time for kernel
1984 * drivers to recover incases like SSR.
1985 */
1986 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001987 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988}
1989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990static int check_input_parameters(uint32_t sample_rate,
1991 audio_format_t format,
1992 int channel_count)
1993{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001994 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301996 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1997 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
1998 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001999 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302000 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002001
2002 switch (channel_count) {
2003 case 1:
2004 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302005 case 3:
2006 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002007 case 6:
2008 break;
2009 default:
2010 ret = -EINVAL;
2011 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012
2013 switch (sample_rate) {
2014 case 8000:
2015 case 11025:
2016 case 12000:
2017 case 16000:
2018 case 22050:
2019 case 24000:
2020 case 32000:
2021 case 44100:
2022 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302023 case 96000:
2024 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025 break;
2026 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002027 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 }
2029
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002030 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031}
2032
2033static size_t get_input_buffer_size(uint32_t sample_rate,
2034 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002035 int channel_count,
2036 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037{
2038 size_t size = 0;
2039
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002040 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2041 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002043 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002044 if (is_low_latency)
2045 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302046
2047 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002049 /* make sure the size is multiple of 32 bytes
2050 * At 48 kHz mono 16-bit PCM:
2051 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2052 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2053 */
2054 size += 0x1f;
2055 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002056
2057 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058}
2059
Ashish Jain5106d362016-05-11 19:23:33 +05302060static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2061{
2062 uint64_t actual_frames_rendered = 0;
2063 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2064
2065 /* This adjustment accounts for buffering after app processor.
2066 * It is based on estimated DSP latency per use case, rather than exact.
2067 */
2068 int64_t platform_latency = platform_render_latency(out->usecase) *
2069 out->sample_rate / 1000000LL;
2070
2071 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2072 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2073 * hence only estimate.
2074 */
2075 int64_t signed_frames = out->written - kernel_buffer_size;
2076
2077 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2078
2079 if (signed_frames > 0)
2080 actual_frames_rendered = signed_frames;
2081
2082 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2083 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2084 (long long int)out->written, (int)kernel_buffer_size,
2085 audio_bytes_per_sample(out->compr_config.codec->format),
2086 popcount(out->channel_mask));
2087
2088 return actual_frames_rendered;
2089}
2090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2092{
2093 struct stream_out *out = (struct stream_out *)stream;
2094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096}
2097
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002098static int out_set_sample_rate(struct audio_stream *stream __unused,
2099 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100{
2101 return -ENOSYS;
2102}
2103
2104static size_t out_get_buffer_size(const struct audio_stream *stream)
2105{
2106 struct stream_out *out = (struct stream_out *)stream;
2107
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002108 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002110 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2111 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002113 return out->config.period_size *
2114 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115}
2116
2117static uint32_t out_get_channels(const struct audio_stream *stream)
2118{
2119 struct stream_out *out = (struct stream_out *)stream;
2120
2121 return out->channel_mask;
2122}
2123
2124static audio_format_t out_get_format(const struct audio_stream *stream)
2125{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 struct stream_out *out = (struct stream_out *)stream;
2127
2128 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129}
2130
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002131static int out_set_format(struct audio_stream *stream __unused,
2132 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133{
2134 return -ENOSYS;
2135}
2136
2137static int out_standby(struct audio_stream *stream)
2138{
2139 struct stream_out *out = (struct stream_out *)stream;
2140 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302142 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2143 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002144 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2145 /* Ignore standby in case of voip call because the voip output
2146 * stream is closed in adev_close_output_stream()
2147 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302148 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002149 return 0;
2150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002152 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002154 if (adev->adm_deregister_stream)
2155 adev->adm_deregister_stream(adev->adm_data, out->handle);
2156
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002157 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002159 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 if (out->pcm) {
2161 pcm_close(out->pcm);
2162 out->pcm = NULL;
2163 }
2164 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002165 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002166 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302167 out->send_next_track_params = false;
2168 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002169 out->gapless_mdata.encoder_delay = 0;
2170 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 if (out->compr != NULL) {
2172 compress_close(out->compr);
2173 out->compr = NULL;
2174 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002175 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002177 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 }
2179 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302180 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 return 0;
2182}
2183
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002184static int out_dump(const struct audio_stream *stream __unused,
2185 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186{
2187 return 0;
2188}
2189
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002190static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2191{
2192 int ret = 0;
2193 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002194
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002195 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002196 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002197 return -EINVAL;
2198 }
2199
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302200 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002201
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002202 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2203 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302204 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002205 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002206 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2207 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302208 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002209 }
2210
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002211 ALOGV("%s new encoder delay %u and padding %u", __func__,
2212 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2213
2214 return 0;
2215}
2216
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002217static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2218{
2219 return out == adev->primary_output || out == adev->voice_tx_output;
2220}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2223{
2224 struct stream_out *out = (struct stream_out *)stream;
2225 struct audio_device *adev = out->dev;
2226 struct str_parms *parms;
2227 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002228 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229
sangwoobc677242013-08-08 16:53:43 +09002230 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002231 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302233 if (!parms)
2234 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002235 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2236 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002238 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002239 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002241 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002242 * When HDMI cable is unplugged the music playback is paused and
2243 * the policy manager sends routing=0. But the audioflinger continues
2244 * to write data until standby time (3sec). As the HDMI core is
2245 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002246 * Avoid this by routing audio to speaker until standby.
2247 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002248 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2249 (val == AUDIO_DEVICE_NONE) &&
2250 !audio_extn_dolby_is_passthrough_stream(out) &&
2251 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2252 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 }
2254
2255 /*
2256 * select_devices() call below switches all the usecases on the same
2257 * backend to the new device. Refer to check_usecases_codec_backend() in
2258 * the select_devices(). But how do we undo this?
2259 *
2260 * For example, music playback is active on headset (deep-buffer usecase)
2261 * and if we go to ringtones and select a ringtone, low-latency usecase
2262 * will be started on headset+speaker. As we can't enable headset+speaker
2263 * and headset devices at the same time, select_devices() switches the music
2264 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2265 * So when the ringtone playback is completed, how do we undo the same?
2266 *
2267 * We are relying on the out_set_parameters() call on deep-buffer output,
2268 * once the ringtone playback is ended.
2269 * NOTE: We should not check if the current devices are same as new devices.
2270 * Because select_devices() must be called to switch back the music
2271 * playback to headset.
2272 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002273 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002274 out->devices = val;
2275
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302276 if (!out->standby) {
2277 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2278 adev->perf_lock_opts,
2279 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302281 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2282 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002283
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002284 if (output_drives_call(adev, out)) {
2285 if(!voice_is_in_call(adev)) {
2286 if (adev->mode == AUDIO_MODE_IN_CALL) {
2287 adev->current_call_output = out;
2288 ret = voice_start_call(adev);
2289 }
2290 } else {
2291 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002292 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002293 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002294 }
2295 }
2296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002298 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002300
2301 if (out == adev->primary_output) {
2302 pthread_mutex_lock(&adev->lock);
2303 audio_extn_set_parameters(adev, parms);
2304 pthread_mutex_unlock(&adev->lock);
2305 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002306 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002307 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002308 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002309
2310 audio_extn_dts_create_state_notifier_node(out->usecase);
2311 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2312 popcount(out->channel_mask),
2313 out->playback_started);
2314
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002315 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002316 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302319error:
Eric Laurent994a6932013-07-17 11:51:42 -07002320 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 return ret;
2322}
2323
2324static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2325{
2326 struct stream_out *out = (struct stream_out *)stream;
2327 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002328 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 char value[256];
2330 struct str_parms *reply = str_parms_create();
2331 size_t i, j;
2332 int ret;
2333 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002334
2335 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002336 if (reply) {
2337 str_parms_destroy(reply);
2338 }
2339 if (query) {
2340 str_parms_destroy(query);
2341 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002342 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2343 return NULL;
2344 }
2345
Eric Laurent994a6932013-07-17 11:51:42 -07002346 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2348 if (ret >= 0) {
2349 value[0] = '\0';
2350 i = 0;
2351 while (out->supported_channel_masks[i] != 0) {
2352 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2353 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2354 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002355 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002357 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 first = false;
2359 break;
2360 }
2361 }
2362 i++;
2363 }
2364 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2365 str = str_parms_to_str(reply);
2366 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002367 voice_extn_out_get_parameters(out, query, reply);
2368 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002369 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002370 free(str);
2371 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002372 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002374
Alexy Joseph62142aa2015-11-16 15:10:34 -08002375
2376 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2377 if (ret >= 0) {
2378 value[0] = '\0';
2379 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2380 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302381 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002382 } else {
2383 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302384 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002385 }
2386 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002387 if (str)
2388 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002389 str = str_parms_to_str(reply);
2390 }
2391
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002392 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2393 if (ret >= 0) {
2394 value[0] = '\0';
2395 i = 0;
2396 first = true;
2397 while (out->supported_formats[i] != 0) {
2398 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2399 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2400 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002401 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002402 }
2403 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2404 first = false;
2405 break;
2406 }
2407 }
2408 i++;
2409 }
2410 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002411 if (str)
2412 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002413 str = str_parms_to_str(reply);
2414 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002415
2416 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2417 if (ret >= 0) {
2418 value[0] = '\0';
2419 i = 0;
2420 first = true;
2421 while (out->supported_sample_rates[i] != 0) {
2422 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2423 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2424 if (!first) {
2425 strlcat(value, "|", sizeof(value));
2426 }
2427 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2428 first = false;
2429 break;
2430 }
2431 }
2432 i++;
2433 }
2434 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2435 if (str)
2436 free(str);
2437 str = str_parms_to_str(reply);
2438 }
2439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 str_parms_destroy(query);
2441 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002442 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 return str;
2444}
2445
2446static uint32_t out_get_latency(const struct audio_stream_out *stream)
2447{
2448 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002449 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450
Alexy Josephaa54c872014-12-03 02:46:47 -08002451 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002452 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002453 } else {
2454 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002456 }
2457
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302458 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002459 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460}
2461
2462static int out_set_volume(struct audio_stream_out *stream, float left,
2463 float right)
2464{
Eric Laurenta9024de2013-04-04 09:19:12 -07002465 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 int volume[2];
2467
Eric Laurenta9024de2013-04-04 09:19:12 -07002468 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2469 /* only take left channel into account: the API is for stereo anyway */
2470 out->muted = (left == 0.0f);
2471 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002472 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002473 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002474 /*
2475 * Set mute or umute on HDMI passthrough stream.
2476 * Only take left channel into account.
2477 * Mute is 0 and unmute 1
2478 */
2479 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2480 } else {
2481 char mixer_ctl_name[128];
2482 struct audio_device *adev = out->dev;
2483 struct mixer_ctl *ctl;
2484 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002485 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002486
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002487 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2488 "Compress Playback %d Volume", pcm_device_id);
2489 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2490 if (!ctl) {
2491 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2492 __func__, mixer_ctl_name);
2493 return -EINVAL;
2494 }
2495 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2496 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2497 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2498 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002500 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 return -ENOSYS;
2503}
2504
2505static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2506 size_t bytes)
2507{
2508 struct stream_out *out = (struct stream_out *)stream;
2509 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302510 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002511 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002513 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302514
Naresh Tanniru80659832014-06-04 18:17:56 +05302515 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002516
Ashish Jainbbce4322016-02-16 13:25:27 +05302517 if (is_offload_usecase(out->usecase)) {
2518 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302519 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2520 pthread_mutex_unlock(&out->lock);
2521 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302522 } else {
2523 /* increase written size during SSR to avoid mismatch
2524 * with the written frames count in AF
2525 */
2526 out->written += bytes / (out->config.channels * sizeof(short));
2527 ALOGD(" %s: sound card is not active/SSR state", __func__);
2528 ret= -EIO;
2529 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302530 }
2531 }
2532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002534 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002535 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002536 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2537 ret = voice_extn_compress_voip_start_output_stream(out);
2538 else
2539 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002541 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002543 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 goto exit;
2545 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002546
2547 if (last_known_cal_step != -1) {
2548 ALOGD("%s: retry previous failed cal level set", __func__);
2549 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2550 }
2551
vivek mehta446c3962015-09-14 10:57:35 -07002552 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002553 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555
Ashish Jain81eb2a82015-05-13 10:52:34 +05302556 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002557 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302558 adev->is_channel_status_set = true;
2559 }
2560
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002561 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002562 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002563 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002564 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002565 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2566 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302567 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2568 ALOGD("copl(%p):send next track params in gapless", out);
2569 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2570 out->send_next_track_params = false;
2571 out->is_compr_metadata_avail = false;
2572 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002573 }
2574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302576 if (ret < 0)
2577 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302578 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002579 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302580 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002581 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302582 } else if (-ENETRESET == ret) {
2583 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2584 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2585 pthread_mutex_unlock(&out->lock);
2586 out_standby(&out->stream.common);
2587 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588 }
Ashish Jain5106d362016-05-11 19:23:33 +05302589 if ( ret == (ssize_t)bytes && !out->non_blocking)
2590 out->written += bytes;
2591
Naresh Tanniru80659832014-06-04 18:17:56 +05302592 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002593 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002594 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 out->playback_started = 1;
2596 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002597
2598 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2599 popcount(out->channel_mask),
2600 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002601 }
2602 pthread_mutex_unlock(&out->lock);
2603 return ret;
2604 } else {
2605 if (out->pcm) {
2606 if (out->muted)
2607 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002608
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302609 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002610
2611 if (adev->adm_request_focus)
2612 adev->adm_request_focus(adev->adm_data, out->handle);
2613
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002614 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2615 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2616 else
2617 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002618
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302619 if (ret < 0)
2620 ret = -errno;
2621 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002622 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002623
2624 if (adev->adm_abandon_focus)
2625 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 }
2628
2629exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302630 /* ToDo: There may be a corner case when SSR happens back to back during
2631 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302632 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302633 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302634 }
2635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 pthread_mutex_unlock(&out->lock);
2637
2638 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002639 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002640 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302641 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302642 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302643 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302644 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302645 out->standby = true;
2646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302648 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302649 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 }
2651 return bytes;
2652}
2653
2654static int out_get_render_position(const struct audio_stream_out *stream,
2655 uint32_t *dsp_frames)
2656{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302658 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002659
2660 if (dsp_frames == NULL)
2661 return -EINVAL;
2662
2663 *dsp_frames = 0;
2664 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002665 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302666
2667 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2668 * this operation and adev_close_output_stream(where out gets reset).
2669 */
2670 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2671 *dsp_frames = get_actual_pcm_frames_rendered(out);
2672 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2673 return 0;
2674 }
2675
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002676 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302677 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302678 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002679 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302680 if (ret < 0)
2681 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002682 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302683 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002684 }
2685 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302686 if (-ENETRESET == ret) {
2687 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2688 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2689 return -EINVAL;
2690 } else if(ret < 0) {
2691 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2692 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302693 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2694 /*
2695 * Handle corner case where compress session is closed during SSR
2696 * and timestamp is queried
2697 */
2698 ALOGE(" ERROR: sound card not active, return error");
2699 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302700 } else {
2701 return 0;
2702 }
Zhou Song32a556e2015-05-05 10:46:56 +08002703 } else if (audio_is_linear_pcm(out->format)) {
2704 *dsp_frames = out->written;
2705 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002706 } else
2707 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708}
2709
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002710static int out_add_audio_effect(const struct audio_stream *stream __unused,
2711 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712{
2713 return 0;
2714}
2715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002716static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2717 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718{
2719 return 0;
2720}
2721
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002722static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2723 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724{
2725 return -EINVAL;
2726}
2727
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002728static int out_get_presentation_position(const struct audio_stream_out *stream,
2729 uint64_t *frames, struct timespec *timestamp)
2730{
2731 struct stream_out *out = (struct stream_out *)stream;
2732 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002733 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002734
Ashish Jain5106d362016-05-11 19:23:33 +05302735 /* below piece of code is not guarded against any lock because audioFliner serializes
2736 * this operation and adev_close_output_stream( where out gets reset).
2737 */
2738 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2739 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2740 *frames = get_actual_pcm_frames_rendered(out);
2741 /* this is the best we can do */
2742 clock_gettime(CLOCK_MONOTONIC, timestamp);
2743 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2744 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2745 return 0;
2746 }
2747
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002748 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002749
Ashish Jain5106d362016-05-11 19:23:33 +05302750 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2751 ret = compress_get_tstamp(out->compr, &dsp_frames,
2752 &out->sample_rate);
2753 ALOGVV("%s rendered frames %ld sample_rate %d",
2754 __func__, dsp_frames, out->sample_rate);
2755 *frames = dsp_frames;
2756 if (ret < 0)
2757 ret = -errno;
2758 if (-ENETRESET == ret) {
2759 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2760 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2761 ret = -EINVAL;
2762 } else
2763 ret = 0;
2764 /* this is the best we can do */
2765 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002766 } else {
2767 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002768 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002769 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2770 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002771 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002772 // This adjustment accounts for buffering after app processor.
2773 // It is based on estimated DSP latency per use case, rather than exact.
2774 signed_frames -=
2775 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2776
Eric Laurent949a0892013-09-20 09:20:13 -07002777 // It would be unusual for this value to be negative, but check just in case ...
2778 if (signed_frames >= 0) {
2779 *frames = signed_frames;
2780 ret = 0;
2781 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002782 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302783 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2784 *frames = out->written;
2785 clock_gettime(CLOCK_MONOTONIC, timestamp);
2786 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002787 }
2788 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002789 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002790 return ret;
2791}
2792
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793static int out_set_callback(struct audio_stream_out *stream,
2794 stream_callback_t callback, void *cookie)
2795{
2796 struct stream_out *out = (struct stream_out *)stream;
2797
2798 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002799 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 out->offload_callback = callback;
2801 out->offload_cookie = cookie;
2802 pthread_mutex_unlock(&out->lock);
2803 return 0;
2804}
2805
2806static int out_pause(struct audio_stream_out* stream)
2807{
2808 struct stream_out *out = (struct stream_out *)stream;
2809 int status = -ENOSYS;
2810 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002811 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002812 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002813 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302815 struct audio_device *adev = out->dev;
2816 int snd_scard_state = get_snd_card_state(adev);
2817
2818 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2819 status = compress_pause(out->compr);
2820
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002822
Mingming Yin21854652016-04-13 11:54:02 -07002823 if (audio_extn_passthru_is_active()) {
2824 ALOGV("offload use case, pause passthru");
2825 audio_extn_passthru_on_pause(out);
2826 }
2827
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302828 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002829 audio_extn_dts_notify_playback_state(out->usecase, 0,
2830 out->sample_rate, popcount(out->channel_mask),
2831 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 }
2833 pthread_mutex_unlock(&out->lock);
2834 }
2835 return status;
2836}
2837
2838static int out_resume(struct audio_stream_out* stream)
2839{
2840 struct stream_out *out = (struct stream_out *)stream;
2841 int status = -ENOSYS;
2842 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002843 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002844 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002846 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302848 struct audio_device *adev = out->dev;
2849 int snd_scard_state = get_snd_card_state(adev);
2850
Mingming Yin21854652016-04-13 11:54:02 -07002851 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2852 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2853 pthread_mutex_lock(&out->dev->lock);
2854 ALOGV("offload resume, check and set hdmi backend again");
2855 check_and_set_hdmi_backend(out);
2856 pthread_mutex_unlock(&out->dev->lock);
2857 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302858 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002859 }
2860 if (!status) {
2861 out->offload_state = OFFLOAD_STATE_PLAYING;
2862 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302863 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002864 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2865 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 }
2867 pthread_mutex_unlock(&out->lock);
2868 }
2869 return status;
2870}
2871
2872static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2873{
2874 struct stream_out *out = (struct stream_out *)stream;
2875 int status = -ENOSYS;
2876 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002877 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002878 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2880 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2881 else
2882 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2883 pthread_mutex_unlock(&out->lock);
2884 }
2885 return status;
2886}
2887
2888static int out_flush(struct audio_stream_out* stream)
2889{
2890 struct stream_out *out = (struct stream_out *)stream;
2891 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002892 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002893 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002894 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302896 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002898 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 return 0;
2900 }
2901 return -ENOSYS;
2902}
2903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904/** audio_stream_in implementation **/
2905static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2906{
2907 struct stream_in *in = (struct stream_in *)stream;
2908
2909 return in->config.rate;
2910}
2911
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002912static int in_set_sample_rate(struct audio_stream *stream __unused,
2913 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914{
2915 return -ENOSYS;
2916}
2917
2918static size_t in_get_buffer_size(const struct audio_stream *stream)
2919{
2920 struct stream_in *in = (struct stream_in *)stream;
2921
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002922 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2923 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002924 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2925 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002926
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002927 return in->config.period_size *
2928 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929}
2930
2931static uint32_t in_get_channels(const struct audio_stream *stream)
2932{
2933 struct stream_in *in = (struct stream_in *)stream;
2934
2935 return in->channel_mask;
2936}
2937
2938static audio_format_t in_get_format(const struct audio_stream *stream)
2939{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002940 struct stream_in *in = (struct stream_in *)stream;
2941
2942 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943}
2944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002945static int in_set_format(struct audio_stream *stream __unused,
2946 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947{
2948 return -ENOSYS;
2949}
2950
2951static int in_standby(struct audio_stream *stream)
2952{
2953 struct stream_in *in = (struct stream_in *)stream;
2954 struct audio_device *adev = in->dev;
2955 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302956 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2957 stream, in->usecase, use_case_table[in->usecase]);
2958
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002959 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2960 /* Ignore standby in case of voip call because the voip input
2961 * stream is closed in adev_close_input_stream()
2962 */
2963 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2964 return status;
2965 }
2966
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002967 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002968 if (!in->standby && in->is_st_session) {
2969 ALOGD("%s: sound trigger pcm stop lab", __func__);
2970 audio_extn_sound_trigger_stop_lab(in);
2971 in->standby = 1;
2972 }
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002975 if (adev->adm_deregister_stream)
2976 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2977
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002978 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002980 if (in->pcm) {
2981 pcm_close(in->pcm);
2982 in->pcm = NULL;
2983 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002985 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 }
2987 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002988 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 return status;
2990}
2991
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002992static int in_dump(const struct audio_stream *stream __unused,
2993 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994{
2995 return 0;
2996}
2997
2998static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2999{
3000 struct stream_in *in = (struct stream_in *)stream;
3001 struct audio_device *adev = in->dev;
3002 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003004 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303006 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 parms = str_parms_create_str(kvpairs);
3008
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303009 if (!parms)
3010 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003011 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003012 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003013
3014 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3015 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 val = atoi(value);
3017 /* no audio source uses val == 0 */
3018 if ((in->source != val) && (val != 0)) {
3019 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003020 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3021 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3022 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003023 (in->config.rate == 8000 || in->config.rate == 16000 ||
3024 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003025 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003026 err = voice_extn_compress_voip_open_input_stream(in);
3027 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003028 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003029 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003030 }
3031 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 }
3033 }
3034
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003035 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3036 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003038 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 in->device = val;
3040 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003041 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003042 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 }
3044 }
3045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003047 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048
3049 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303050error:
Eric Laurent994a6932013-07-17 11:51:42 -07003051 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 return ret;
3053}
3054
3055static char* in_get_parameters(const struct audio_stream *stream,
3056 const char *keys)
3057{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003058 struct stream_in *in = (struct stream_in *)stream;
3059 struct str_parms *query = str_parms_create_str(keys);
3060 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003062
3063 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003064 if (reply) {
3065 str_parms_destroy(reply);
3066 }
3067 if (query) {
3068 str_parms_destroy(query);
3069 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003070 ALOGE("in_get_parameters: failed to create query or reply");
3071 return NULL;
3072 }
3073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003074 ALOGV("%s: enter: keys - %s", __func__, keys);
3075
3076 voice_extn_in_get_parameters(in, query, reply);
3077
3078 str = str_parms_to_str(reply);
3079 str_parms_destroy(query);
3080 str_parms_destroy(reply);
3081
3082 ALOGV("%s: exit: returns - %s", __func__, str);
3083 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084}
3085
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003086static int in_set_gain(struct audio_stream_in *stream __unused,
3087 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088{
3089 return 0;
3090}
3091
3092static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3093 size_t bytes)
3094{
3095 struct stream_in *in = (struct stream_in *)stream;
3096 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303097 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303098 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303099 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003101 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303102
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003103 if (in->is_st_session) {
3104 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3105 /* Read from sound trigger HAL */
3106 audio_extn_sound_trigger_read(in, buffer, bytes);
3107 pthread_mutex_unlock(&in->lock);
3108 return bytes;
3109 }
3110
Ashish Jainbbce4322016-02-16 13:25:27 +05303111 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003112 ALOGD(" %s: sound card is not active/SSR state", __func__);
3113 ret= -EIO;;
3114 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303115 }
3116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003118 pthread_mutex_lock(&adev->lock);
3119 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3120 ret = voice_extn_compress_voip_start_input_stream(in);
3121 else
3122 ret = start_input_stream(in);
3123 pthread_mutex_unlock(&adev->lock);
3124 if (ret != 0) {
3125 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 }
3127 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003128 if (adev->adm_register_input_stream)
3129 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003132 if (adev->adm_request_focus)
3133 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303136 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003137 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303138 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003139 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303140 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003141 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303142 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003143 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303144 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3145 if (bytes % 4 == 0) {
3146 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3147 int_buf_stream = buffer;
3148 for (size_t itt=0; itt < bytes/4 ; itt++) {
3149 int_buf_stream[itt] >>= 8;
3150 }
3151 } else {
3152 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3153 ret = -EINVAL;
3154 goto exit;
3155 }
3156 } if (ret < 0) {
3157 ret = -errno;
3158 }
3159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160 }
3161
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003162 if (adev->adm_abandon_focus)
3163 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 /*
3166 * Instead of writing zeroes here, we could trust the hardware
3167 * to always provide zeroes when muted.
3168 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303169 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3170 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 memset(buffer, 0, bytes);
3172
3173exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303174 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303175 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003176 if (-ENETRESET == ret)
3177 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 pthread_mutex_unlock(&in->lock);
3180
3181 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303182 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303183 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303184 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303185 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303186 in->standby = true;
3187 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303188 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003190 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303191 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303192 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 }
3194 return bytes;
3195}
3196
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003197static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198{
3199 return 0;
3200}
3201
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003202static int add_remove_audio_effect(const struct audio_stream *stream,
3203 effect_handle_t effect,
3204 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003206 struct stream_in *in = (struct stream_in *)stream;
3207 int status = 0;
3208 effect_descriptor_t desc;
3209
3210 status = (*effect)->get_descriptor(effect, &desc);
3211 if (status != 0)
3212 return status;
3213
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003214 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003215 pthread_mutex_lock(&in->dev->lock);
3216 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3217 in->enable_aec != enable &&
3218 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3219 in->enable_aec = enable;
3220 if (!in->standby)
3221 select_devices(in->dev, in->usecase);
3222 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003223 if (in->enable_ns != enable &&
3224 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3225 in->enable_ns = enable;
3226 if (!in->standby)
3227 select_devices(in->dev, in->usecase);
3228 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003229 pthread_mutex_unlock(&in->dev->lock);
3230 pthread_mutex_unlock(&in->lock);
3231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 return 0;
3233}
3234
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003235static int in_add_audio_effect(const struct audio_stream *stream,
3236 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237{
Eric Laurent994a6932013-07-17 11:51:42 -07003238 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003239 return add_remove_audio_effect(stream, effect, true);
3240}
3241
3242static int in_remove_audio_effect(const struct audio_stream *stream,
3243 effect_handle_t effect)
3244{
Eric Laurent994a6932013-07-17 11:51:42 -07003245 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003246 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247}
3248
3249static int adev_open_output_stream(struct audio_hw_device *dev,
3250 audio_io_handle_t handle,
3251 audio_devices_t devices,
3252 audio_output_flags_t flags,
3253 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003254 struct audio_stream_out **stream_out,
3255 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256{
3257 struct audio_device *adev = (struct audio_device *)dev;
3258 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303259 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003260 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303263
3264 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3265 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003266 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303267 return -EINVAL;
3268 }
3269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3271
Mingming Yin3a941d42016-02-17 18:08:05 -08003272 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3273 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303274 devices, flags, &out->stream);
3275
3276
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003277 if (!out) {
3278 return -ENOMEM;
3279 }
3280
Haynes Mathew George204045b2015-02-25 20:32:03 -08003281 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003282 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003283 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 if (devices == AUDIO_DEVICE_NONE)
3286 devices = AUDIO_DEVICE_OUT_SPEAKER;
3287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 out->flags = flags;
3289 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003290 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003291 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 out->sample_rate = config->sample_rate;
3293 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3294 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003295 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003296 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003297 out->non_blocking = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298
Mingming Yin3a941d42016-02-17 18:08:05 -08003299 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3300 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3301 pthread_mutex_lock(&adev->lock);
3302 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3303 ret = read_hdmi_sink_caps(out);
3304 pthread_mutex_unlock(&adev->lock);
3305 if (ret != 0) {
3306 if (ret == -ENOSYS) {
3307 /* ignore and go with default */
3308 ret = 0;
3309 } else {
3310 ALOGE("error reading hdmi sink caps");
3311 goto error_open;
3312 }
3313 }
3314 }
3315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003317 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303318 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3319 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003320 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3321 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3322
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003323 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003324 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3325 /*
3326 * Do not handle stereo output in Multi-channel cases
3327 * Stereo case is handled in normal playback path
3328 */
3329 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3330 ret = AUDIO_CHANNEL_OUT_STEREO;
3331 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003332
3333 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3334 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003335 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003336 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003337 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003338
3339 if (config->sample_rate == 0)
3340 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3341 if (config->channel_mask == 0)
3342 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003343 if (config->format == 0)
3344 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003345
3346 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003347 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003348 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3350 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003352 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003354 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3355 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003356 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003357 ret = voice_extn_compress_voip_open_output_stream(out);
3358 if (ret != 0) {
3359 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3360 __func__, ret);
3361 goto error_open;
3362 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003363 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3364 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003366 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3367 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3368 ALOGE("%s: Unsupported Offload information", __func__);
3369 ret = -EINVAL;
3370 goto error_open;
3371 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003372
Mingming Yin3a941d42016-02-17 18:08:05 -08003373 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003374 if(config->offload_info.format == 0)
3375 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003376 if (config->offload_info.sample_rate == 0)
3377 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003378 }
3379
Mingming Yin90310102013-11-13 16:57:00 -08003380 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003381 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003382 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383 ret = -EINVAL;
3384 goto error_open;
3385 }
3386
3387 out->compr_config.codec = (struct snd_codec *)
3388 calloc(1, sizeof(struct snd_codec));
3389
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003390 if (!out->compr_config.codec) {
3391 ret = -ENOMEM;
3392 goto error_open;
3393 }
3394
vivek mehta0ea887a2015-08-26 14:01:20 -07003395 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303396 out->stream.pause = out_pause;
3397 out->stream.flush = out_flush;
3398 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003399 out->usecase = get_offload_usecase(adev, true);
3400 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003401 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003402 out->stream.set_callback = out_set_callback;
3403 out->stream.pause = out_pause;
3404 out->stream.resume = out_resume;
3405 out->stream.drain = out_drain;
3406 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003407 out->usecase = get_offload_usecase(adev, false);
3408 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003409 }
vivek mehta446c3962015-09-14 10:57:35 -07003410
3411 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003412 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3413 config->format == 0 && config->sample_rate == 0 &&
3414 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003415 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003416 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3417 } else {
3418 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3419 ret = -EEXIST;
3420 goto error_open;
3421 }
vivek mehta446c3962015-09-14 10:57:35 -07003422 }
3423
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003424 if (config->offload_info.channel_mask)
3425 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003426 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003427 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003428 config->offload_info.channel_mask = config->channel_mask;
3429 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003430 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 out->sample_rate = config->offload_info.sample_rate;
3432
Mingming Yin3ee55c62014-08-04 14:23:35 -07003433 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003434
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003435 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003436 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003437 audio_extn_dolby_get_snd_codec_id(adev, out,
3438 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003439 else
3440 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003442
Ashish Jain5106d362016-05-11 19:23:33 +05303443 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003444 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003445 platform_get_pcm_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303446 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
Mingming Yin21854652016-04-13 11:54:02 -07003447 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003448 out->compr_config.fragment_size =
3449 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303450 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003451 } else {
3452 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003453 platform_get_compress_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303454 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003455 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003456 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003457 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003458 out->compr_config.codec->bit_rate =
3459 config->offload_info.bit_rate;
3460 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003461 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003462 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303463 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003464 /*TODO: Do we need to change it for passthrough */
3465 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003466
Manish Dewangana6fc5442015-08-24 20:30:31 +05303467 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3468 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3469 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3470 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
vivek mehta0ea887a2015-08-26 14:01:20 -07003471 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3472 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Ashish Jain5106d362016-05-11 19:23:33 +05303473 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
3474 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
3475 if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
Mingming Yin3ee55c62014-08-04 14:23:35 -07003476 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003477
Amit Shekhar6f461b12014-08-01 14:52:58 -07003478 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303479 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003480
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3482 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003483
Alexy Josephaa54c872014-12-03 02:46:47 -08003484
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003485 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303486 out->send_next_track_params = false;
3487 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003488 out->offload_state = OFFLOAD_STATE_IDLE;
3489 out->playback_started = 0;
3490
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003491 audio_extn_dts_create_state_notifier_node(out->usecase);
3492
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003493 create_offload_callback_thread(out);
3494 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3495 __func__, config->offload_info.version,
3496 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303497
3498 /* Disable gapless if any of the following is true
3499 * passthrough playback
3500 * AV playback
3501 * Direct PCM playback
3502 */
3503 if (audio_extn_dolby_is_passthrough_stream(out) ||
3504 config->offload_info.has_video ||
3505 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3506 check_and_set_gapless_mode(adev, false);
3507 } else
3508 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003509
3510 if (audio_extn_dolby_is_passthrough_stream(out)) {
3511 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3512 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003513 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303514 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003515 if (ret != 0) {
3516 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3517 __func__, ret);
3518 goto error_open;
3519 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003520 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3521 if (config->sample_rate == 0)
3522 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3523 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3524 config->sample_rate != 8000) {
3525 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3526 ret = -EINVAL;
3527 goto error_open;
3528 }
3529 out->sample_rate = config->sample_rate;
3530 out->config.rate = config->sample_rate;
3531 if (config->format == AUDIO_FORMAT_DEFAULT)
3532 config->format = AUDIO_FORMAT_PCM_16_BIT;
3533 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3534 config->format = AUDIO_FORMAT_PCM_16_BIT;
3535 ret = -EINVAL;
3536 goto error_open;
3537 }
3538 out->format = config->format;
3539 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3540 out->config = pcm_config_afe_proxy_playback;
3541 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003542 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3543 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3544 out->config = pcm_config_low_latency;
3545 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003546 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003547 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3549 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003551 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3552 format = AUDIO_FORMAT_PCM_16_BIT;
3553 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3554 out->config = pcm_config_deep_buffer;
3555 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003556 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003557 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003558 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003559 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003560 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003561 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 }
3563
Mingming Yin21854652016-04-13 11:54:02 -07003564 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3565 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003566 /* TODO remove this hardcoding and check why width is zero*/
3567 if (out->bit_width == 0)
3568 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003569 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3570 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003571 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303572 out->bit_width, out->channel_mask,
3573 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003574 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3575 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3576 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003577 if(adev->primary_output == NULL)
3578 adev->primary_output = out;
3579 else {
3580 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003581 ret = -EEXIST;
3582 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003583 }
3584 }
3585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 /* Check if this usecase is already existing */
3587 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003588 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3589 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003592 ret = -EEXIST;
3593 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 }
3595 pthread_mutex_unlock(&adev->lock);
3596
3597 out->stream.common.get_sample_rate = out_get_sample_rate;
3598 out->stream.common.set_sample_rate = out_set_sample_rate;
3599 out->stream.common.get_buffer_size = out_get_buffer_size;
3600 out->stream.common.get_channels = out_get_channels;
3601 out->stream.common.get_format = out_get_format;
3602 out->stream.common.set_format = out_set_format;
3603 out->stream.common.standby = out_standby;
3604 out->stream.common.dump = out_dump;
3605 out->stream.common.set_parameters = out_set_parameters;
3606 out->stream.common.get_parameters = out_get_parameters;
3607 out->stream.common.add_audio_effect = out_add_audio_effect;
3608 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3609 out->stream.get_latency = out_get_latency;
3610 out->stream.set_volume = out_set_volume;
3611 out->stream.write = out_write;
3612 out->stream.get_render_position = out_get_render_position;
3613 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003614 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003617 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003618 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619
3620 config->format = out->stream.common.get_format(&out->stream.common);
3621 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3622 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3623
3624 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303625 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003626 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003627
3628 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3629 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3630 popcount(out->channel_mask), out->playback_started);
3631
Eric Laurent994a6932013-07-17 11:51:42 -07003632 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003634
3635error_open:
3636 free(out);
3637 *stream_out = NULL;
3638 ALOGD("%s: exit: ret %d", __func__, ret);
3639 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640}
3641
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003642static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 struct audio_stream_out *stream)
3644{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645 struct stream_out *out = (struct stream_out *)stream;
3646 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003647 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303649 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3650
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003651 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303652 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003653 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303654 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003655 if(ret != 0)
3656 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3657 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003658 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003659 out_standby(&stream->common);
3660
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003661 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003662 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003664 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 if (out->compr_config.codec != NULL)
3666 free(out->compr_config.codec);
3667 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003668
3669 if (adev->voice_tx_output == out)
3670 adev->voice_tx_output = NULL;
3671
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 pthread_cond_destroy(&out->cond);
3673 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003675 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676}
3677
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003678static void close_compress_sessions(struct audio_device *adev)
3679{
Mingming Yin7b762e72015-03-04 13:47:32 -08003680 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303681 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003682 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003683 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303684
3685 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003686 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303687 if (is_offload_usecase(usecase->id)) {
3688 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003689 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3690 out = usecase->stream.out;
3691 pthread_mutex_unlock(&adev->lock);
3692 out_standby(&out->stream.common);
3693 pthread_mutex_lock(&adev->lock);
3694 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303695 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003696 }
3697 pthread_mutex_unlock(&adev->lock);
3698}
3699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3701{
3702 struct audio_device *adev = (struct audio_device *)dev;
3703 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003705 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003706 int ret;
3707 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003709 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303712 if (!parms)
3713 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003714 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3715 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303716 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303717 if (strstr(snd_card_status, "OFFLINE")) {
3718 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303719 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003720 //close compress sessions on OFFLINE status
3721 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303722 } else if (strstr(snd_card_status, "ONLINE")) {
3723 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303724 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003725 //send dts hpx license if enabled
3726 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303727 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303728 }
3729
3730 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003731 status = voice_set_parameters(adev, parms);
3732 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003733 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003735 status = platform_set_parameters(adev->platform, parms);
3736 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003737 goto done;
3738
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003739 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3740 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003741 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3743 adev->bluetooth_nrec = true;
3744 else
3745 adev->bluetooth_nrec = false;
3746 }
3747
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003748 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3749 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3751 adev->screen_off = false;
3752 else
3753 adev->screen_off = true;
3754 }
3755
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003756 ret = str_parms_get_int(parms, "rotation", &val);
3757 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003758 bool reverse_speakers = false;
3759 switch(val) {
3760 // FIXME: note that the code below assumes that the speakers are in the correct placement
3761 // relative to the user when the device is rotated 90deg from its default rotation. This
3762 // assumption is device-specific, not platform-specific like this code.
3763 case 270:
3764 reverse_speakers = true;
3765 break;
3766 case 0:
3767 case 90:
3768 case 180:
3769 break;
3770 default:
3771 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003772 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003773 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003774 if (status == 0) {
3775 if (adev->speaker_lr_swap != reverse_speakers) {
3776 adev->speaker_lr_swap = reverse_speakers;
3777 // only update the selected device if there is active pcm playback
3778 struct audio_usecase *usecase;
3779 struct listnode *node;
3780 list_for_each(node, &adev->usecase_list) {
3781 usecase = node_to_item(node, struct audio_usecase, list);
3782 if (usecase->type == PCM_PLAYBACK) {
3783 select_devices(adev, usecase->id);
3784 break;
3785 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003786 }
3787 }
3788 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003789 }
3790
Mingming Yin514a8bc2014-07-29 15:22:21 -07003791 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3792 if (ret >= 0) {
3793 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3794 adev->bt_wb_speech_enabled = true;
3795 else
3796 adev->bt_wb_speech_enabled = false;
3797 }
3798
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003799 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3800 if (ret >= 0) {
3801 val = atoi(value);
3802 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3803 ALOGV("cache new edid");
3804 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003805 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3806 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07003807 /*
3808 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3809 * Per AudioPolicyManager, USB device is higher priority than WFD.
3810 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3811 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3812 * starting voice call on USB
3813 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003814 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3815 if (ret >= 0) {
3816 audio_extn_usb_add_device(val, atoi(value));
3817 }
vivek mehta344576a2016-04-12 18:56:03 -07003818 ALOGV("detected USB connect .. disable proxy");
3819 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003820 }
3821 }
3822
3823 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3824 if (ret >= 0) {
3825 val = atoi(value);
3826 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3827 ALOGV("invalidate cached edid");
3828 platform_invalidate_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003829 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3830 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
3831 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3832 if (ret >= 0) {
3833 audio_extn_usb_remove_device(val, atoi(value));
3834 }
vivek mehta344576a2016-04-12 18:56:03 -07003835 ALOGV("detected USB disconnect .. enable proxy");
3836 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003837 }
3838 }
3839
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003840 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003841
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003842done:
3843 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003844 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303845error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003846 ALOGV("%s: exit with code(%d)", __func__, status);
3847 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848}
3849
3850static char* adev_get_parameters(const struct audio_hw_device *dev,
3851 const char *keys)
3852{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003853 struct audio_device *adev = (struct audio_device *)dev;
3854 struct str_parms *reply = str_parms_create();
3855 struct str_parms *query = str_parms_create_str(keys);
3856 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303857 char value[256] = {0};
3858 int ret = 0;
3859
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003860 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003861 if (reply) {
3862 str_parms_destroy(reply);
3863 }
3864 if (query) {
3865 str_parms_destroy(query);
3866 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003867 ALOGE("adev_get_parameters: failed to create query or reply");
3868 return NULL;
3869 }
3870
Naresh Tannirud7205b62014-06-20 02:54:48 +05303871 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3872 sizeof(value));
3873 if (ret >=0) {
3874 int val = 1;
3875 pthread_mutex_lock(&adev->snd_card_status.lock);
3876 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3877 val = 0;
3878 pthread_mutex_unlock(&adev->snd_card_status.lock);
3879 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3880 goto exit;
3881 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003882
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003883 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003884 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003885 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003886 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303887 pthread_mutex_unlock(&adev->lock);
3888
Naresh Tannirud7205b62014-06-20 02:54:48 +05303889exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003890 str = str_parms_to_str(reply);
3891 str_parms_destroy(query);
3892 str_parms_destroy(reply);
3893
3894 ALOGV("%s: exit: returns - %s", __func__, str);
3895 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896}
3897
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003898static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899{
3900 return 0;
3901}
3902
3903static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3904{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003905 int ret;
3906 struct audio_device *adev = (struct audio_device *)dev;
3907 pthread_mutex_lock(&adev->lock);
3908 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003909 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003910 pthread_mutex_unlock(&adev->lock);
3911 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912}
3913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003914static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3915 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916{
3917 return -ENOSYS;
3918}
3919
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003920static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3921 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922{
3923 return -ENOSYS;
3924}
3925
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003926static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3927 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928{
3929 return -ENOSYS;
3930}
3931
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003932static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3933 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934{
3935 return -ENOSYS;
3936}
3937
3938static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3939{
3940 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 pthread_mutex_lock(&adev->lock);
3943 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003944 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003946 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003947 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003948 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003949 adev->current_call_output = NULL;
3950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 }
3952 pthread_mutex_unlock(&adev->lock);
3953 return 0;
3954}
3955
3956static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3957{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003958 int ret;
3959
3960 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003961 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003962 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3963 pthread_mutex_unlock(&adev->lock);
3964
3965 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966}
3967
3968static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3969{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003970 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 return 0;
3972}
3973
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003974static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975 const struct audio_config *config)
3976{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003977 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003979 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3980 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981}
3982
3983static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003984 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985 audio_devices_t devices,
3986 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003987 struct audio_stream_in **stream_in,
3988 audio_input_flags_t flags __unused,
3989 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003990 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991{
3992 struct audio_device *adev = (struct audio_device *)dev;
3993 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003994 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003995 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003996 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303999 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4000 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304002 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003
4004 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004005
4006 if (!in) {
4007 ALOGE("failed to allocate input stream");
4008 return -ENOMEM;
4009 }
4010
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304011 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304012 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4013 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004014 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004015 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017 in->stream.common.get_sample_rate = in_get_sample_rate;
4018 in->stream.common.set_sample_rate = in_set_sample_rate;
4019 in->stream.common.get_buffer_size = in_get_buffer_size;
4020 in->stream.common.get_channels = in_get_channels;
4021 in->stream.common.get_format = in_get_format;
4022 in->stream.common.set_format = in_set_format;
4023 in->stream.common.standby = in_standby;
4024 in->stream.common.dump = in_dump;
4025 in->stream.common.set_parameters = in_set_parameters;
4026 in->stream.common.get_parameters = in_get_parameters;
4027 in->stream.common.add_audio_effect = in_add_audio_effect;
4028 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4029 in->stream.set_gain = in_set_gain;
4030 in->stream.read = in_read;
4031 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4032
4033 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004034 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 in->standby = 1;
4037 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004038 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004039 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040
4041 /* Update config params with the requested sample rate and channels */
4042 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004043 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4044 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4045 is_low_latency = true;
4046#if LOW_LATENCY_CAPTURE_USE_CASE
4047 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4048#endif
4049 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004052 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304053 in->bit_width = 16;
4054 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004056 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304057 if (adev->mode != AUDIO_MODE_IN_CALL) {
4058 ret = -EINVAL;
4059 goto err_open;
4060 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004061 if (config->sample_rate == 0)
4062 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4063 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4064 config->sample_rate != 8000) {
4065 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4066 ret = -EINVAL;
4067 goto err_open;
4068 }
4069 if (config->format == AUDIO_FORMAT_DEFAULT)
4070 config->format = AUDIO_FORMAT_PCM_16_BIT;
4071 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4072 config->format = AUDIO_FORMAT_PCM_16_BIT;
4073 ret = -EINVAL;
4074 goto err_open;
4075 }
4076
4077 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4078 in->config = pcm_config_afe_proxy_record;
4079 in->config.channels = channel_count;
4080 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304081 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304082 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4083 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004084 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004085 audio_extn_compr_cap_format_supported(config->format) &&
4086 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004087 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004088 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304089 /* restrict 24 bit capture for unprocessed source only
4090 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4091 */
4092 if (config->format == AUDIO_FORMAT_DEFAULT) {
4093 config->format = AUDIO_FORMAT_PCM_16_BIT;
4094 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4095 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4096 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4097 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4098 bool ret_error = false;
4099 in->bit_width = 24;
4100 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4101 from HAL is 24_packed and 8_24
4102 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4103 24_packed return error indicating supported format is 24_packed
4104 *> In case of any other source requesting 24 bit or float return error
4105 indicating format supported is 16 bit only.
4106
4107 on error flinger will retry with supported format passed
4108 */
4109 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4110 (source != AUDIO_SOURCE_CAMCORDER)) {
4111 config->format = AUDIO_FORMAT_PCM_16_BIT;
4112 if( config->sample_rate > 48000)
4113 config->sample_rate = 48000;
4114 ret_error = true;
4115 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4116 in->config.format = PCM_FORMAT_S24_3LE;
4117 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4118 in->config.format = PCM_FORMAT_S24_LE;
4119 } else {
4120 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4121 ret_error = true;
4122 }
4123
4124 if (ret_error) {
4125 ret = -EINVAL;
4126 goto err_open;
4127 }
4128 }
4129
4130 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004131 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004132 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004133 buffer_size = get_input_buffer_size(config->sample_rate,
4134 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004135 channel_count,
4136 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004137 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004138 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4139 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4140 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004141 (in->config.rate == 8000 || in->config.rate == 16000 ||
4142 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004143 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4144 voice_extn_compress_voip_open_input_stream(in);
4145 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004148 /* This stream could be for sound trigger lab,
4149 get sound trigger pcm if present */
4150 audio_extn_sound_trigger_check_and_get_session(in);
4151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004153 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155
4156err_open:
4157 free(in);
4158 *stream_in = NULL;
4159 return ret;
4160}
4161
4162static void adev_close_input_stream(struct audio_hw_device *dev,
4163 struct audio_stream_in *stream)
4164{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004165 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004166 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004167 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304168
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304169 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004170
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304171 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004172 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304173
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004174 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304175 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004176 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304177 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004178 if (ret != 0)
4179 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4180 __func__, ret);
4181 } else
4182 in_standby(&stream->common);
4183
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004184 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004185 audio_extn_ssr_deinit();
4186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187
Mingming Yine62d7842013-10-25 16:26:03 -07004188 if(audio_extn_compr_cap_enabled() &&
4189 audio_extn_compr_cap_format_supported(in->config.format))
4190 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004191
Mingming Yinfd7607b2016-01-22 12:48:44 -08004192 if (in->is_st_session) {
4193 ALOGV("%s: sound trigger pcm stop lab", __func__);
4194 audio_extn_sound_trigger_stop_lab(in);
4195 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004196 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 return;
4198}
4199
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004200static int adev_dump(const audio_hw_device_t *device __unused,
4201 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202{
4203 return 0;
4204}
4205
4206static int adev_close(hw_device_t *device)
4207{
4208 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004209
4210 if (!adev)
4211 return 0;
4212
4213 pthread_mutex_lock(&adev_init_lock);
4214
4215 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004216 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004217 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004218 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004219 audio_route_free(adev->audio_route);
4220 free(adev->snd_dev_ref_cnt);
4221 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004222 if (adev->adm_deinit)
4223 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004224 free(device);
4225 adev = NULL;
4226 }
4227 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 return 0;
4230}
4231
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004232/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4233 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4234 * just that it _might_ work.
4235 */
4236static int period_size_is_plausible_for_low_latency(int period_size)
4237{
4238 switch (period_size) {
4239 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004240 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004241 case 240:
4242 case 320:
4243 case 480:
4244 return 1;
4245 default:
4246 return 0;
4247 }
4248}
4249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250static int adev_open(const hw_module_t *module, const char *name,
4251 hw_device_t **device)
4252{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004253 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4255
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004256 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004257 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004258 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004259 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004260 ALOGD("%s: returning existing instance of adev", __func__);
4261 ALOGD("%s: exit", __func__);
4262 pthread_mutex_unlock(&adev_init_lock);
4263 return 0;
4264 }
4265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266 adev = calloc(1, sizeof(struct audio_device));
4267
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004268 if (!adev) {
4269 pthread_mutex_unlock(&adev_init_lock);
4270 return -ENOMEM;
4271 }
4272
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004273 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004275 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4276 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4277 adev->device.common.module = (struct hw_module_t *)module;
4278 adev->device.common.close = adev_close;
4279
4280 adev->device.init_check = adev_init_check;
4281 adev->device.set_voice_volume = adev_set_voice_volume;
4282 adev->device.set_master_volume = adev_set_master_volume;
4283 adev->device.get_master_volume = adev_get_master_volume;
4284 adev->device.set_master_mute = adev_set_master_mute;
4285 adev->device.get_master_mute = adev_get_master_mute;
4286 adev->device.set_mode = adev_set_mode;
4287 adev->device.set_mic_mute = adev_set_mic_mute;
4288 adev->device.get_mic_mute = adev_get_mic_mute;
4289 adev->device.set_parameters = adev_set_parameters;
4290 adev->device.get_parameters = adev_get_parameters;
4291 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4292 adev->device.open_output_stream = adev_open_output_stream;
4293 adev->device.close_output_stream = adev_close_output_stream;
4294 adev->device.open_input_stream = adev_open_input_stream;
4295 adev->device.close_input_stream = adev_close_input_stream;
4296 adev->device.dump = adev_dump;
4297
4298 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004300 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004301 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004304 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004305 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004306 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004307 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004308 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004309 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004310 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004311 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304312 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304313 adev->perf_lock_opts[0] = 0x101;
4314 adev->perf_lock_opts[1] = 0x20E;
4315 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304316
4317 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4318 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004320 adev->platform = platform_init(adev);
4321 if (!adev->platform) {
4322 free(adev->snd_dev_ref_cnt);
4323 free(adev);
4324 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4325 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004326 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004327 return -EINVAL;
4328 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004329
Naresh Tanniru4c630392014-05-12 01:05:52 +05304330 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4331
Eric Laurentc4aef752013-09-12 17:45:53 -07004332 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4333 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4334 if (adev->visualizer_lib == NULL) {
4335 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4336 } else {
4337 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4338 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004339 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004340 "visualizer_hal_start_output");
4341 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004342 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004343 "visualizer_hal_stop_output");
4344 }
4345 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004346 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004347 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004348
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004349 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4350 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4351 if (adev->offload_effects_lib == NULL) {
4352 ALOGE("%s: DLOPEN failed for %s", __func__,
4353 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4354 } else {
4355 ALOGV("%s: DLOPEN successful for %s", __func__,
4356 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4357 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304358 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004359 "offload_effects_bundle_hal_start_output");
4360 adev->offload_effects_stop_output =
4361 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4362 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004363 adev->offload_effects_set_hpx_state =
4364 (int (*)(bool))dlsym(adev->offload_effects_lib,
4365 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304366 adev->offload_effects_get_parameters =
4367 (void (*)(struct str_parms *, struct str_parms *))
4368 dlsym(adev->offload_effects_lib,
4369 "offload_effects_bundle_get_parameters");
4370 adev->offload_effects_set_parameters =
4371 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4372 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004373 }
4374 }
4375
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004376 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4377 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4378 if (adev->adm_lib == NULL) {
4379 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4380 } else {
4381 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4382 adev->adm_init = (adm_init_t)
4383 dlsym(adev->adm_lib, "adm_init");
4384 adev->adm_deinit = (adm_deinit_t)
4385 dlsym(adev->adm_lib, "adm_deinit");
4386 adev->adm_register_input_stream = (adm_register_input_stream_t)
4387 dlsym(adev->adm_lib, "adm_register_input_stream");
4388 adev->adm_register_output_stream = (adm_register_output_stream_t)
4389 dlsym(adev->adm_lib, "adm_register_output_stream");
4390 adev->adm_deregister_stream = (adm_deregister_stream_t)
4391 dlsym(adev->adm_lib, "adm_deregister_stream");
4392 adev->adm_request_focus = (adm_request_focus_t)
4393 dlsym(adev->adm_lib, "adm_request_focus");
4394 adev->adm_abandon_focus = (adm_abandon_focus_t)
4395 dlsym(adev->adm_lib, "adm_abandon_focus");
4396 }
4397 }
4398
Mingming Yin514a8bc2014-07-29 15:22:21 -07004399 adev->bt_wb_speech_enabled = false;
4400
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004401 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402 *device = &adev->device.common;
4403
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004404 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4405 &adev->streams_output_cfg_list);
4406
Kiran Kandi910e1862013-10-29 13:29:42 -07004407 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004408
4409 char value[PROPERTY_VALUE_MAX];
4410 int trial;
4411 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4412 trial = atoi(value);
4413 if (period_size_is_plausible_for_low_latency(trial)) {
4414 pcm_config_low_latency.period_size = trial;
4415 pcm_config_low_latency.start_threshold = trial / 4;
4416 pcm_config_low_latency.avail_min = trial / 4;
4417 configured_low_latency_capture_period_size = trial;
4418 }
4419 }
4420 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4421 trial = atoi(value);
4422 if (period_size_is_plausible_for_low_latency(trial)) {
4423 configured_low_latency_capture_period_size = trial;
4424 }
4425 }
4426
vivek mehta446c3962015-09-14 10:57:35 -07004427 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004428 pthread_mutex_unlock(&adev_init_lock);
4429
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004430 if (adev->adm_init)
4431 adev->adm_data = adev->adm_init();
4432
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304433 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004434 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004435 return 0;
4436}
4437
4438static struct hw_module_methods_t hal_module_methods = {
4439 .open = adev_open,
4440};
4441
4442struct audio_module HAL_MODULE_INFO_SYM = {
4443 .common = {
4444 .tag = HARDWARE_MODULE_TAG,
4445 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4446 .hal_api_version = HARDWARE_HAL_API_VERSION,
4447 .id = AUDIO_HARDWARE_MODULE_ID,
4448 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004449 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450 .methods = &hal_module_methods,
4451 },
4452};