blob: aabb656f5cf3abd77454cc2709e13a077a300b5b [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 /* start usb playback thread */
541 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
542 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
543 audio_extn_usb_start_playback(adev);
544
545 /* start usb capture thread */
546 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
547 audio_extn_usb_start_capture(adev);
548
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800549 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
550 audio_extn_spkr_prot_is_enabled()) {
551 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700552 adev->snd_dev_ref_cnt[snd_device]--;
553 return -EINVAL;
554 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200555 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800556 if (audio_extn_spkr_prot_start_processing(snd_device)) {
557 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200558 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 return -EINVAL;
560 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530561 } else if (platform_can_split_snd_device(adev->platform, snd_device,
562 &num_devices, new_snd_devices)) {
563 for (i = 0; i < num_devices; i++) {
564 enable_snd_device(adev, new_snd_devices[i]);
565 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800566 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700567 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700568 /* due to the possibility of calibration overwrite between listen
569 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700570 audio_extn_sound_trigger_update_device_status(snd_device,
571 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530572 audio_extn_listen_update_device_status(snd_device,
573 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700574 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700575 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700576 audio_extn_sound_trigger_update_device_status(snd_device,
577 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530578 audio_extn_listen_update_device_status(snd_device,
579 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700580 return -EINVAL;
581 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300582 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700583 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530584
585 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
586 !adev->native_playback_enabled &&
587 audio_is_true_native_stream_active(adev)) {
588 ALOGD("%s: %d: napb: enabling native mode in hardware",
589 __func__, __LINE__);
590 audio_route_apply_and_update_path(adev->audio_route,
591 "true-native-mode");
592 adev->native_playback_enabled = true;
593 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800594 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800595 return 0;
596}
597
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700598int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700599 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800600{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530601 int i, num_devices = 0;
602 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700603 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
604
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800605 if (snd_device < SND_DEVICE_MIN ||
606 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800607 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800608 return -EINVAL;
609 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
611 ALOGE("%s: device ref cnt is already 0", __func__);
612 return -EINVAL;
613 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700614
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700616
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700617 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
618 ALOGE("%s: Invalid sound device returned", __func__);
619 return -EINVAL;
620 }
621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700623 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800624 /* exit usb play back thread */
625 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
626 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
627 audio_extn_usb_stop_playback();
628
629 /* exit usb capture thread */
630 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700631 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800632
633 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
634 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700635 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530636 } else if (platform_can_split_snd_device(adev->platform, snd_device,
637 &num_devices, new_snd_devices)) {
638 for (i = 0; i < num_devices; i++) {
639 disable_snd_device(adev, new_snd_devices[i]);
640 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300641 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700642 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300643 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700644
Ashish Jain81eb2a82015-05-13 10:52:34 +0530645 if (snd_device == SND_DEVICE_OUT_HDMI)
646 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530647 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
648 adev->native_playback_enabled) {
649 ALOGD("%s: %d: napb: disabling native mode in hardware",
650 __func__, __LINE__);
651 audio_route_reset_and_update_path(adev->audio_route,
652 "true-native-mode");
653 adev->native_playback_enabled = false;
654 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530655
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200656 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700657 audio_extn_sound_trigger_update_device_status(snd_device,
658 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530659 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800660 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800663 return 0;
664}
665
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530667 struct audio_usecase *uc_info,
668 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669{
670 struct listnode *node;
671 struct audio_usecase *usecase;
672 bool switch_device[AUDIO_USECASE_MAX];
673 int i, num_uc_to_switch = 0;
674
675 /*
676 * This function is to make sure that all the usecases that are active on
677 * the hardware codec backend are always routed to any one device that is
678 * handled by the hardware codec.
679 * For example, if low-latency and deep-buffer usecases are currently active
680 * on speaker and out_set_parameters(headset) is received on low-latency
681 * output, then we have to make sure deep-buffer is also switched to headset,
682 * because of the limitation that both the devices cannot be enabled
683 * at the same time as they share the same backend.
684 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700685 /*
686 * This call is to check if we need to force routing for a particular stream
687 * If there is a backend configuration change for the device when a
688 * new stream starts, then ADM needs to be closed and re-opened with the new
689 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800690 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700691 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800692 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
693 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530694
695 ALOGD("%s:becf: force routing %d", __func__, force_routing);
696
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700697 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800698 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800699 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700700 for (i = 0; i < AUDIO_USECASE_MAX; i++)
701 switch_device[i] = false;
702
703 list_for_each(node, &adev->usecase_list) {
704 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800705
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530706 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
707 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530708 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530709 platform_get_snd_device_name(usecase->out_snd_device),
710 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800711 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530712 usecase != uc_info &&
713 (usecase->out_snd_device != snd_device || force_routing) &&
714 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
715 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
716 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
717 __func__, use_case_table[usecase->id],
718 platform_get_snd_device_name(usecase->out_snd_device));
719 disable_audio_route(adev, usecase);
720 switch_device[usecase->id] = true;
721 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 }
723 }
724
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530725 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
726 num_uc_to_switch);
727
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700729 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700730
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530731 /* Make sure the previous devices to be disabled first and then enable the
732 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700733 list_for_each(node, &adev->usecase_list) {
734 usecase = node_to_item(node, struct audio_usecase, list);
735 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700736 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 }
738 }
739
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700740 list_for_each(node, &adev->usecase_list) {
741 usecase = node_to_item(node, struct audio_usecase, list);
742 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700743 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700744 }
745 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700746
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 /* Re-route all the usecases on the shared backend other than the
748 specified usecase to new snd devices */
749 list_for_each(node, &adev->usecase_list) {
750 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530751 /* Update the out_snd_device only before enabling the audio route */
752 if (switch_device[usecase->id]) {
753 usecase->out_snd_device = snd_device;
754 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530755 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530756 use_case_table[usecase->id],
757 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530758 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760 }
761 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762 }
763}
764
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530765static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 struct audio_usecase *uc_info,
767 snd_device_t snd_device)
768{
769 struct listnode *node;
770 struct audio_usecase *usecase;
771 bool switch_device[AUDIO_USECASE_MAX];
772 int i, num_uc_to_switch = 0;
773
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530774 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
775 snd_device);
776 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700777 /*
778 * This function is to make sure that all the active capture usecases
779 * are always routed to the same input sound device.
780 * For example, if audio-record and voice-call usecases are currently
781 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
782 * is received for voice call then we have to make sure that audio-record
783 * usecase is also switched to earpiece i.e. voice-dmic-ef,
784 * because of the limitation that two devices cannot be enabled
785 * at the same time if they share the same backend.
786 */
787 for (i = 0; i < AUDIO_USECASE_MAX; i++)
788 switch_device[i] = false;
789
790 list_for_each(node, &adev->usecase_list) {
791 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800792 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700793 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530794 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700795 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530796 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
797 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700798 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
800 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700801 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700802 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700803 switch_device[usecase->id] = true;
804 num_uc_to_switch++;
805 }
806 }
807
808 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700809 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700810
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530811 /* Make sure the previous devices to be disabled first and then enable the
812 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700813 list_for_each(node, &adev->usecase_list) {
814 usecase = node_to_item(node, struct audio_usecase, list);
815 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700816 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800817 }
818 }
819
820 list_for_each(node, &adev->usecase_list) {
821 usecase = node_to_item(node, struct audio_usecase, list);
822 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700823 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700824 }
825 }
826
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700827 /* Re-route all the usecases on the shared backend other than the
828 specified usecase to new snd devices */
829 list_for_each(node, &adev->usecase_list) {
830 usecase = node_to_item(node, struct audio_usecase, list);
831 /* Update the in_snd_device only before enabling the audio route */
832 if (switch_device[usecase->id] ) {
833 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800834 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530835 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700836 }
837 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700838 }
839}
840
Mingming Yin3a941d42016-02-17 18:08:05 -0800841static void reset_hdmi_sink_caps(struct stream_out *out) {
842 int i = 0;
843
844 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
845 out->supported_channel_masks[i] = 0;
846 }
847 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
848 out->supported_formats[i] = 0;
849 }
850 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
851 out->supported_sample_rates[i] = 0;
852 }
853}
854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -0800856static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857{
Mingming Yin3a941d42016-02-17 18:08:05 -0800858 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700859 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860
Mingming Yin3a941d42016-02-17 18:08:05 -0800861 reset_hdmi_sink_caps(out);
862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -0800865 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700866 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -0800867 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
868 case 6:
869 ALOGV("%s: HDMI supports 5.1 channels", __func__);
870 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
871 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
872 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
873 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
874 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
875 case 2:
876 ALOGV("%s: HDMI supports 2 channels", __func__);
877 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_STEREO;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 break;
879 default:
Mingming Yin3a941d42016-02-17 18:08:05 -0800880 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700881 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800882 break;
883 }
Mingming Yin3a941d42016-02-17 18:08:05 -0800884
885 // check channel format caps
886 i = 0;
887 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
888 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
889 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
890 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
891 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
892 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
893 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
894 }
895
896 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
897 ALOGV(":%s HDMI supports DTS format", __func__);
898 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
899 }
900
901 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
902 ALOGV(":%s HDMI supports DTS HD format", __func__);
903 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
904 }
905
906
907 // check sample rate caps
908 i = 0;
909 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
910 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
911 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
912 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
913 }
914 }
915
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700916 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800917}
918
Alexy Josephb1379942016-01-29 15:49:38 -0800919audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800920 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -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);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800927 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700928 ALOGV("%s: usecase id %d", __func__, usecase->id);
929 return usecase->id;
930 }
931 }
932 return USECASE_INVALID;
933}
934
Alexy Josephb1379942016-01-29 15:49:38 -0800935struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700936 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700937{
938 struct audio_usecase *usecase;
939 struct listnode *node;
940
941 list_for_each(node, &adev->usecase_list) {
942 usecase = node_to_item(node, struct audio_usecase, list);
943 if (usecase->id == uc_id)
944 return usecase;
945 }
946 return NULL;
947}
948
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530949/*
950 * is a true native playback active
951 */
952bool audio_is_true_native_stream_active(struct audio_device *adev)
953{
954 bool active = false;
955 int i = 0;
956 struct listnode *node;
957
958 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
959 ALOGV("%s:napb: not in true mode or non hdphones device",
960 __func__);
961 active = false;
962 goto exit;
963 }
964
965 list_for_each(node, &adev->usecase_list) {
966 struct audio_usecase *uc;
967 uc = node_to_item(node, struct audio_usecase, list);
968 struct stream_out *curr_out =
969 (struct stream_out*) uc->stream.out;
970
971 if (curr_out && PCM_PLAYBACK == uc->type) {
972 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
973 "(%d) device %s", __func__, i++, use_case_table[uc->id],
974 uc->id, curr_out->sample_rate,
975 curr_out->bit_width,
976 platform_get_snd_device_name(uc->out_snd_device));
977
978 if (is_offload_usecase(uc->id) &&
979 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
980 active = true;
981 ALOGD("%s:napb:native stream detected", __func__);
982 }
983 }
984 }
985exit:
986 return active;
987}
988
989
990static bool force_device_switch(struct audio_usecase *usecase)
991{
992 bool ret = false;
993 bool is_it_true_mode = false;
994
995 if (is_offload_usecase(usecase->id) &&
996 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800997 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
998 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
999 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301000 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1001 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1002 (!is_it_true_mode && adev->native_playback_enabled)){
1003 ret = true;
1004 ALOGD("napb: time to toggle native mode");
1005 }
1006 }
1007
1008 return ret;
1009}
1010
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001011int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001013 snd_device_t out_snd_device = SND_DEVICE_NONE;
1014 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015 struct audio_usecase *usecase = NULL;
1016 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001017 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001018 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001019 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301022 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1023
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001024 usecase = get_usecase_from_list(adev, uc_id);
1025 if (usecase == NULL) {
1026 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1027 return -EINVAL;
1028 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001030 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001031 (usecase->type == VOIP_CALL) ||
1032 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001033 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001034 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001035 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001036 usecase->devices = usecase->stream.out->devices;
1037 } else {
1038 /*
1039 * If the voice call is active, use the sound devices of voice call usecase
1040 * so that it would not result any device switch. All the usecases will
1041 * be switched to new device when select_devices() is called for voice call
1042 * usecase. This is to avoid switching devices for voice call when
1043 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001044 * choose voice call device only if the use case device is
1045 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001046 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001047 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001048 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001049 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001050 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1051 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1052 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001053 in_snd_device = vc_usecase->in_snd_device;
1054 out_snd_device = vc_usecase->out_snd_device;
1055 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001056 } else if (voice_extn_compress_voip_is_active(adev)) {
1057 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001058 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301059 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001060 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001061 in_snd_device = voip_usecase->in_snd_device;
1062 out_snd_device = voip_usecase->out_snd_device;
1063 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001064 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001065 hfp_ucid = audio_extn_hfp_get_usecase();
1066 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001067 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001068 in_snd_device = hfp_usecase->in_snd_device;
1069 out_snd_device = hfp_usecase->out_snd_device;
1070 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 }
1072 if (usecase->type == PCM_PLAYBACK) {
1073 usecase->devices = usecase->stream.out->devices;
1074 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001075 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001076 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001077 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001078 if (usecase->stream.out == adev->primary_output &&
1079 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001080 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001081 select_devices(adev, adev->active_input->usecase);
1082 }
1083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 } else if (usecase->type == PCM_CAPTURE) {
1085 usecase->devices = usecase->stream.in->device;
1086 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001087 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001088 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001089 if (adev->active_input &&
1090 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301091 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1092 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1093 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001094 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001095 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001096 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1097 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001098 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001099 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001100 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 }
1102 }
1103
1104 if (out_snd_device == usecase->out_snd_device &&
1105 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301106
1107 if (!force_device_switch(usecase))
1108 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
1110
sangwoobc677242013-08-08 16:53:43 +09001111 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001112 out_snd_device, platform_get_snd_device_name(out_snd_device),
1113 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 /*
1116 * Limitation: While in call, to do a device switch we need to disable
1117 * and enable both RX and TX devices though one of them is same as current
1118 * device.
1119 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001120 if ((usecase->type == VOICE_CALL) &&
1121 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1122 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001123 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001124 }
1125
1126 if (((usecase->type == VOICE_CALL) ||
1127 (usecase->type == VOIP_CALL)) &&
1128 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1129 /* Disable sidetone only if voice/voip call already exists */
1130 if (voice_is_call_state_active(adev) ||
1131 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001132 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001133 }
1134
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 /* Disable current sound devices */
1136 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001137 disable_audio_route(adev, usecase);
1138 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 }
1140
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001142 disable_audio_route(adev, usecase);
1143 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001144 }
1145
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001146 /* Applicable only on the targets that has external modem.
1147 * New device information should be sent to modem before enabling
1148 * the devices to reduce in-call device switch time.
1149 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001150 if ((usecase->type == VOICE_CALL) &&
1151 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1152 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001153 status = platform_switch_voice_call_enable_device_config(adev->platform,
1154 out_snd_device,
1155 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001156 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001157
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 /* Enable new sound devices */
1159 if (out_snd_device != SND_DEVICE_NONE) {
1160 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1161 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001162 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163 }
1164
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001165 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301166 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001167 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001168 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169
Avinash Vaish71a8b972014-07-24 15:36:33 +05301170 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001171 status = platform_switch_voice_call_device_post(adev->platform,
1172 out_snd_device,
1173 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301174 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001175 /* Enable sidetone only if voice/voip call already exists */
1176 if (voice_is_call_state_active(adev) ||
1177 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001178 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301179 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001180
sangwoo170731f2013-06-08 15:36:36 +09001181 usecase->in_snd_device = in_snd_device;
1182 usecase->out_snd_device = out_snd_device;
1183
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301184 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001185 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301186 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001187 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301188 usecase->stream.out->flags,
1189 usecase->stream.out->format,
1190 usecase->stream.out->sample_rate,
1191 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301192 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301193 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001194 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301195 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001196
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001197 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001198
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001199 /* Applicable only on the targets that has external modem.
1200 * Enable device command should be sent to modem only after
1201 * enabling voice call mixer controls
1202 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001203 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001204 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1205 out_snd_device,
1206 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301207 ALOGD("%s: done",__func__);
1208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 return status;
1210}
1211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212static int stop_input_stream(struct stream_in *in)
1213{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301214 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001215 struct audio_usecase *uc_info;
1216 struct audio_device *adev = in->dev;
1217
Eric Laurentc8400632013-02-14 19:04:54 -08001218 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219
Eric Laurent994a6932013-07-17 11:51:42 -07001220 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001221 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001222 uc_info = get_usecase_from_list(adev, in->usecase);
1223 if (uc_info == NULL) {
1224 ALOGE("%s: Could not find the usecase (%d) in the list",
1225 __func__, in->usecase);
1226 return -EINVAL;
1227 }
1228
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001229 /* Close in-call recording streams */
1230 voice_check_and_stop_incall_rec_usecase(adev, in);
1231
Eric Laurent150dbfe2013-02-27 14:31:02 -08001232 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001233 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234
1235 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001236 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001237
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001238 list_remove(&uc_info->list);
1239 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001240
Eric Laurent994a6932013-07-17 11:51:42 -07001241 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 return ret;
1243}
1244
1245int start_input_stream(struct stream_in *in)
1246{
1247 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001248 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 struct audio_usecase *uc_info;
1250 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301251 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
Mingming Yin2664a5b2015-09-03 10:53:11 -07001253 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1254 if (get_usecase_from_list(adev, usecase) == NULL)
1255 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301256 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1257 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001258
Naresh Tanniru80659832014-06-04 18:17:56 +05301259
1260 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301261 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301262 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301263 goto error_config;
1264 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301265
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001266 /* Check if source matches incall recording usecase criteria */
1267 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1268 if (ret)
1269 goto error_config;
1270 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001271 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1272
1273 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1274 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1275 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001276 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001277 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001278
Eric Laurentb23d5282013-05-14 15:27:20 -07001279 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 if (in->pcm_device_id < 0) {
1281 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1282 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001283 ret = -EINVAL;
1284 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286
1287 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001289
1290 if (!uc_info) {
1291 ret = -ENOMEM;
1292 goto error_config;
1293 }
1294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 uc_info->id = in->usecase;
1296 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001297 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 uc_info->devices = in->device;
1299 uc_info->in_snd_device = SND_DEVICE_NONE;
1300 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001302 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301303 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1304 adev->perf_lock_opts,
1305 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001307
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301308 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1309 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001310
1311 unsigned int flags = PCM_IN;
1312 unsigned int pcm_open_retry_count = 0;
1313
1314 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1315 flags |= PCM_MMAP | PCM_NOIRQ;
1316 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1317 }
1318
1319 while (1) {
1320 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1321 flags, &in->config);
1322 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1323 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1324 if (in->pcm != NULL) {
1325 pcm_close(in->pcm);
1326 in->pcm = NULL;
1327 }
1328 if (pcm_open_retry_count-- == 0) {
1329 ret = -EIO;
1330 goto error_open;
1331 }
1332 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1333 continue;
1334 }
1335 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001337
1338 ALOGV("%s: pcm_prepare", __func__);
1339 ret = pcm_prepare(in->pcm);
1340 if (ret < 0) {
1341 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1342 pcm_close(in->pcm);
1343 in->pcm = NULL;
1344 goto error_open;
1345 }
1346
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301347 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001348 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001349
Eric Laurentc8400632013-02-14 19:04:54 -08001350 return ret;
1351
1352error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301353 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001354 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001355error_config:
1356 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301357 /*
1358 * sleep 50ms to allow sufficient time for kernel
1359 * drivers to recover incases like SSR.
1360 */
1361 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001362 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001363
1364 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365}
1366
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001367void lock_input_stream(struct stream_in *in)
1368{
1369 pthread_mutex_lock(&in->pre_lock);
1370 pthread_mutex_lock(&in->lock);
1371 pthread_mutex_unlock(&in->pre_lock);
1372}
1373
1374void lock_output_stream(struct stream_out *out)
1375{
1376 pthread_mutex_lock(&out->pre_lock);
1377 pthread_mutex_lock(&out->lock);
1378 pthread_mutex_unlock(&out->pre_lock);
1379}
1380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381/* must be called with out->lock locked */
1382static int send_offload_cmd_l(struct stream_out* out, int command)
1383{
1384 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1385
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001386 if (!cmd) {
1387 ALOGE("failed to allocate mem for command 0x%x", command);
1388 return -ENOMEM;
1389 }
1390
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001391 ALOGVV("%s %d", __func__, command);
1392
1393 cmd->cmd = command;
1394 list_add_tail(&out->offload_cmd_list, &cmd->node);
1395 pthread_cond_signal(&out->offload_cond);
1396 return 0;
1397}
1398
1399/* must be called iwth out->lock locked */
1400static void stop_compressed_output_l(struct stream_out *out)
1401{
1402 out->offload_state = OFFLOAD_STATE_IDLE;
1403 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001404 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001405 if (out->compr != NULL) {
1406 compress_stop(out->compr);
1407 while (out->offload_thread_blocked) {
1408 pthread_cond_wait(&out->cond, &out->lock);
1409 }
1410 }
1411}
1412
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001413bool is_offload_usecase(audio_usecase_t uc_id)
1414{
1415 unsigned int i;
1416 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1417 if (uc_id == offload_usecases[i])
1418 return true;
1419 }
1420 return false;
1421}
1422
vivek mehta446c3962015-09-14 10:57:35 -07001423static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001424{
vivek mehta446c3962015-09-14 10:57:35 -07001425 audio_usecase_t ret_uc = USECASE_INVALID;
1426 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001427 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001428 if (!adev->multi_offload_enable) {
1429 if (is_direct_pcm)
1430 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1431 else
1432 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001433
vivek mehta446c3962015-09-14 10:57:35 -07001434 pthread_mutex_lock(&adev->lock);
1435 if (get_usecase_from_list(adev, ret_uc) != NULL)
1436 ret_uc = USECASE_INVALID;
1437 pthread_mutex_unlock(&adev->lock);
1438
1439 return ret_uc;
1440 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001441
1442 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001443 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1444 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1445 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1446 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001447 break;
1448 }
1449 }
vivek mehta446c3962015-09-14 10:57:35 -07001450
1451 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1452 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001453}
1454
1455static void free_offload_usecase(struct audio_device *adev,
1456 audio_usecase_t uc_id)
1457{
vivek mehta446c3962015-09-14 10:57:35 -07001458 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001459 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001460
1461 if (!adev->multi_offload_enable)
1462 return;
1463
1464 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1465 if (offload_usecases[offload_uc_index] == uc_id) {
1466 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001467 break;
1468 }
1469 }
1470 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1471}
1472
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473static void *offload_thread_loop(void *context)
1474{
1475 struct stream_out *out = (struct stream_out *) context;
1476 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001477 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001478
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001479 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1480 set_sched_policy(0, SP_FOREGROUND);
1481 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1482
1483 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001484 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001485 for (;;) {
1486 struct offload_cmd *cmd = NULL;
1487 stream_callback_event_t event;
1488 bool send_callback = false;
1489
1490 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1491 __func__, list_empty(&out->offload_cmd_list),
1492 out->offload_state);
1493 if (list_empty(&out->offload_cmd_list)) {
1494 ALOGV("%s SLEEPING", __func__);
1495 pthread_cond_wait(&out->offload_cond, &out->lock);
1496 ALOGV("%s RUNNING", __func__);
1497 continue;
1498 }
1499
1500 item = list_head(&out->offload_cmd_list);
1501 cmd = node_to_item(item, struct offload_cmd, node);
1502 list_remove(item);
1503
1504 ALOGVV("%s STATE %d CMD %d out->compr %p",
1505 __func__, out->offload_state, cmd->cmd, out->compr);
1506
1507 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1508 free(cmd);
1509 break;
1510 }
1511
1512 if (out->compr == NULL) {
1513 ALOGE("%s: Compress handle is NULL", __func__);
1514 pthread_cond_signal(&out->cond);
1515 continue;
1516 }
1517 out->offload_thread_blocked = true;
1518 pthread_mutex_unlock(&out->lock);
1519 send_callback = false;
1520 switch(cmd->cmd) {
1521 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001522 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001523 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001524 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001525 send_callback = true;
1526 event = STREAM_CBK_EVENT_WRITE_READY;
1527 break;
1528 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001529 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301530 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001531 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301532 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001533 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301534 if (ret < 0)
1535 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301536 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301537 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001538 compress_drain(out->compr);
1539 else
1540 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301541 if (ret != -ENETRESET) {
1542 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301543 pthread_mutex_lock(&out->lock);
1544 out->send_new_metadata = 1;
1545 out->send_next_track_params = true;
1546 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301547 event = STREAM_CBK_EVENT_DRAIN_READY;
1548 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1549 } else
1550 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001551 break;
1552 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001553 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001554 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001555 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001556 send_callback = true;
1557 event = STREAM_CBK_EVENT_DRAIN_READY;
1558 break;
1559 default:
1560 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1561 break;
1562 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001563 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001564 out->offload_thread_blocked = false;
1565 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001566 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001567 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001568 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001569 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001570 free(cmd);
1571 }
1572
1573 pthread_cond_signal(&out->cond);
1574 while (!list_empty(&out->offload_cmd_list)) {
1575 item = list_head(&out->offload_cmd_list);
1576 list_remove(item);
1577 free(node_to_item(item, struct offload_cmd, node));
1578 }
1579 pthread_mutex_unlock(&out->lock);
1580
1581 return NULL;
1582}
1583
1584static int create_offload_callback_thread(struct stream_out *out)
1585{
1586 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1587 list_init(&out->offload_cmd_list);
1588 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1589 offload_thread_loop, out);
1590 return 0;
1591}
1592
1593static int destroy_offload_callback_thread(struct stream_out *out)
1594{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001595 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596 stop_compressed_output_l(out);
1597 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1598
1599 pthread_mutex_unlock(&out->lock);
1600 pthread_join(out->offload_thread, (void **) NULL);
1601 pthread_cond_destroy(&out->offload_cond);
1602
1603 return 0;
1604}
1605
Mingming Yin21854652016-04-13 11:54:02 -07001606static bool allow_hdmi_channel_config(struct audio_device *adev,
1607 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001608{
1609 struct listnode *node;
1610 struct audio_usecase *usecase;
1611 bool ret = true;
1612
Mingming Yin21854652016-04-13 11:54:02 -07001613 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1614 ret = false;
1615 goto exit;
1616 }
1617
1618 if (audio_extn_passthru_is_active()) {
1619 ALOGI("%s: Compress audio passthrough is active,"
1620 "no HDMI config change allowed", __func__);
1621 ret = false;
1622 goto exit;
1623 }
1624
Eric Laurent07eeafd2013-10-06 12:52:49 -07001625 list_for_each(node, &adev->usecase_list) {
1626 usecase = node_to_item(node, struct audio_usecase, list);
1627 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1628 /*
1629 * If voice call is already existing, do not proceed further to avoid
1630 * disabling/enabling both RX and TX devices, CSD calls, etc.
1631 * Once the voice call done, the HDMI channels can be configured to
1632 * max channels of remaining use cases.
1633 */
1634 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001635 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 __func__);
1637 ret = false;
1638 break;
1639 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001640 if (!enable_passthru) {
1641 ALOGV("%s: multi channel playback is active, "
1642 "no change in HDMI channels", __func__);
1643 ret = false;
1644 break;
1645 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001646 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001647 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001648 if (!enable_passthru) {
1649 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1650 ", no change in HDMI channels", __func__,
1651 usecase->stream.out->channel_mask);
1652 ret = false;
1653 break;
1654 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001655 }
1656 }
1657 }
Mingming Yin21854652016-04-13 11:54:02 -07001658 ALOGV("allow hdmi config %d", ret);
1659exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001660 return ret;
1661}
1662
Mingming Yin21854652016-04-13 11:54:02 -07001663static int check_and_set_hdmi_config(struct audio_device *adev,
1664 uint32_t channels,
1665 uint32_t sample_rate,
1666 audio_format_t format,
1667 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001668{
1669 struct listnode *node;
1670 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001671 int32_t factor = 1;
1672 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001673
Mingming Yin21854652016-04-13 11:54:02 -07001674 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1675 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001676
Mingming Yin21854652016-04-13 11:54:02 -07001677 if (channels != adev->cur_hdmi_channels) {
1678 ALOGV("channel does not match current hdmi channels");
1679 config = true;
1680 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001681
Mingming Yin21854652016-04-13 11:54:02 -07001682 if (sample_rate != adev->cur_hdmi_sample_rate) {
1683 ALOGV("sample rate does not match current hdmi sample rate");
1684 config = true;
1685 }
1686
1687 if (format != adev->cur_hdmi_format) {
1688 ALOGV("format does not match current hdmi format");
1689 config = true;
1690 }
1691
1692 /* TBD - add check for bit width */
1693 if (!config) {
1694 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001695 return 0;
1696 }
1697
Mingming Yin21854652016-04-13 11:54:02 -07001698 if (enable_passthru &&
1699 (format == AUDIO_FORMAT_E_AC3)) {
1700 ALOGV("factor 4 for E_AC3 passthru");
1701 factor = 4;
1702 }
1703
1704 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1705 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001706 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001707 adev->cur_hdmi_format = format;
1708 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001709
1710 /*
1711 * Deroute all the playback streams routed to HDMI so that
1712 * the back end is deactivated. Note that backend will not
1713 * be deactivated if any one stream is connected to it.
1714 */
1715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
1717 if (usecase->type == PCM_PLAYBACK &&
1718 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001719 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001720 }
1721 }
1722
Mingming Yin21854652016-04-13 11:54:02 -07001723 bool was_active = audio_extn_keep_alive_is_active();
1724 if (was_active)
1725 audio_extn_keep_alive_stop();
1726
Eric Laurent07eeafd2013-10-06 12:52:49 -07001727 /*
1728 * Enable all the streams disabled above. Now the HDMI backend
1729 * will be activated with new channel configuration
1730 */
1731 list_for_each(node, &adev->usecase_list) {
1732 usecase = node_to_item(node, struct audio_usecase, list);
1733 if (usecase->type == PCM_PLAYBACK &&
1734 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001735 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001736 }
1737 }
1738
Mingming Yin21854652016-04-13 11:54:02 -07001739 if (was_active)
1740 audio_extn_keep_alive_start();
1741
Eric Laurent07eeafd2013-10-06 12:52:49 -07001742 return 0;
1743}
1744
Mingming Yin21854652016-04-13 11:54:02 -07001745/* called with out lock taken */
1746static int check_and_set_hdmi_backend(struct stream_out *out)
1747{
1748 struct audio_device *adev = out->dev;
1749 int ret;
1750 bool enable_passthru = false;
1751
1752 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1753 return -1;
1754
1755 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1756
1757 if (is_offload_usecase(out->usecase) &&
1758 audio_extn_dolby_is_passthrough_stream(out)) {
1759 enable_passthru = true;
1760 }
1761
1762 /* Check if change in HDMI channel config is allowed */
1763 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1764 return -EPERM;
1765 }
1766
1767 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1768 uint32_t channels;
1769 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1770
1771 if (enable_passthru) {
1772 audio_extn_passthru_on_start(out);
1773 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1774 }
1775
1776 /* For pass through case, the backend should be configured as stereo */
1777 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1778 out->compr_config.codec->ch_in;
1779
1780 ret = check_and_set_hdmi_config(adev, channels,
1781 out->sample_rate, out->format,
1782 enable_passthru);
1783 } else
1784 ret = check_and_set_hdmi_config(adev, out->config.channels,
1785 out->config.rate,
1786 out->format,
1787 false);
1788 return ret;
1789}
1790
1791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792static int stop_output_stream(struct stream_out *out)
1793{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301794 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 struct audio_usecase *uc_info;
1796 struct audio_device *adev = out->dev;
1797
Eric Laurent994a6932013-07-17 11:51:42 -07001798 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001799 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 uc_info = get_usecase_from_list(adev, out->usecase);
1801 if (uc_info == NULL) {
1802 ALOGE("%s: Could not find the usecase (%d) in the list",
1803 __func__, out->usecase);
1804 return -EINVAL;
1805 }
1806
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001807 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001808 !(audio_extn_dolby_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001809 if (adev->visualizer_stop_output != NULL)
1810 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001811
1812 audio_extn_dts_remove_state_notifier_node(out->usecase);
1813
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001814 if (adev->offload_effects_stop_output != NULL)
1815 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1816 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001817
Eric Laurent150dbfe2013-02-27 14:31:02 -08001818 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001819 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001820
1821 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001822 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001824 list_remove(&uc_info->list);
1825 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001827 if (is_offload_usecase(out->usecase) &&
Mingming Yin21854652016-04-13 11:54:02 -07001828 (audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001829 ALOGV("Disable passthrough , reset mixer to pcm");
1830 /* NO_PASSTHROUGH */
1831 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001832
1833 /* Must be called after removing the usecase from list */
1834 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1835 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
1836 DEFAULT_HDMI_OUT_SAMPLE_RATE,
1837 DEFAULT_HDMI_OUT_FORMAT,
1838 false);
1839 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001840 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1841 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001842
Eric Laurent994a6932013-07-17 11:51:42 -07001843 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844 return ret;
1845}
1846
1847int start_output_stream(struct stream_out *out)
1848{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 struct audio_usecase *uc_info;
1851 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301852 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001854 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1855 ret = -EINVAL;
1856 goto error_config;
1857 }
1858
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301859 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1860 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1861 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301862
Naresh Tanniru80659832014-06-04 18:17:56 +05301863 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301864 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301865 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301866 goto error_config;
1867 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301868
Eric Laurentb23d5282013-05-14 15:27:20 -07001869 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 if (out->pcm_device_id < 0) {
1871 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1872 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001873 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001874 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 }
1876
1877 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001878
1879 if (!uc_info) {
1880 ret = -ENOMEM;
1881 goto error_config;
1882 }
1883
Mingming Yin21854652016-04-13 11:54:02 -07001884 /* This must be called before adding this usecase to the list */
1885 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1886 /* This call can fail if compress pass thru is already active */
1887 check_and_set_hdmi_backend(out);
1888 }
1889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890 uc_info->id = out->usecase;
1891 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001892 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001893 uc_info->devices = out->devices;
1894 uc_info->in_snd_device = SND_DEVICE_NONE;
1895 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001896 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301898 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1899 adev->perf_lock_opts,
1900 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 select_devices(adev, out->usecase);
1902
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001903 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1904 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001905 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001906 unsigned int flags = PCM_OUT;
1907 unsigned int pcm_open_retry_count = 0;
1908 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1909 flags |= PCM_MMAP | PCM_NOIRQ;
1910 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1911 } else
1912 flags |= PCM_MONOTONIC;
1913
1914 while (1) {
1915 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1916 flags, &out->config);
1917 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1918 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1919 if (out->pcm != NULL) {
1920 pcm_close(out->pcm);
1921 out->pcm = NULL;
1922 }
1923 if (pcm_open_retry_count-- == 0) {
1924 ret = -EIO;
1925 goto error_open;
1926 }
1927 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1928 continue;
1929 }
1930 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001932
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001933 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1934 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001935
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001936 ALOGV("%s: pcm_prepare", __func__);
1937 if (pcm_is_ready(out->pcm)) {
1938 ret = pcm_prepare(out->pcm);
1939 if (ret < 0) {
1940 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1941 pcm_close(out->pcm);
1942 out->pcm = NULL;
1943 goto error_open;
1944 }
1945 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001947 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1948 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001950 out->compr = compress_open(adev->snd_card,
1951 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 COMPRESS_IN, &out->compr_config);
1953 if (out->compr && !is_compress_ready(out->compr)) {
1954 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1955 compress_close(out->compr);
1956 out->compr = NULL;
1957 ret = -EIO;
1958 goto error_open;
1959 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301960 /* compress_open sends params of the track, so reset the flag here */
1961 out->is_compr_metadata_avail = false;
1962
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963 if (out->offload_callback)
1964 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001965
Fred Oh3f43e742015-03-04 18:42:34 -08001966 /* Since small bufs uses blocking writes, a write will be blocked
1967 for the default max poll time (20s) in the event of an SSR.
1968 Reduce the poll time to observe and deal with SSR faster.
1969 */
Ashish Jain5106d362016-05-11 19:23:33 +05301970 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001971 compress_set_max_poll_wait(out->compr, 1000);
1972 }
1973
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001974 audio_extn_dts_create_state_notifier_node(out->usecase);
1975 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1976 popcount(out->channel_mask),
1977 out->playback_started);
1978
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001979#ifdef DS1_DOLBY_DDP_ENABLED
1980 if (audio_extn_is_dolby_format(out->format))
1981 audio_extn_dolby_send_ddp_endp_params(adev);
1982#endif
Mingming Yin21854652016-04-13 11:54:02 -07001983 if (!(audio_extn_dolby_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001984 if (adev->visualizer_start_output != NULL)
1985 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1986 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05301987 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001988 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001989 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301991 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001992 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001995error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301996 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001998error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301999 /*
2000 * sleep 50ms to allow sufficient time for kernel
2001 * drivers to recover incases like SSR.
2002 */
2003 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002004 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005}
2006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007static int check_input_parameters(uint32_t sample_rate,
2008 audio_format_t format,
2009 int channel_count)
2010{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002011 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302013 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2014 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2015 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002016 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302017 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002018
2019 switch (channel_count) {
2020 case 1:
2021 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302022 case 3:
2023 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002024 case 6:
2025 break;
2026 default:
2027 ret = -EINVAL;
2028 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029
2030 switch (sample_rate) {
2031 case 8000:
2032 case 11025:
2033 case 12000:
2034 case 16000:
2035 case 22050:
2036 case 24000:
2037 case 32000:
2038 case 44100:
2039 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302040 case 96000:
2041 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 break;
2043 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002044 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 }
2046
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002047 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048}
2049
2050static size_t get_input_buffer_size(uint32_t sample_rate,
2051 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002052 int channel_count,
2053 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054{
2055 size_t size = 0;
2056
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002057 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2058 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002060 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002061 if (is_low_latency)
2062 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302063
2064 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002066 /* make sure the size is multiple of 32 bytes
2067 * At 48 kHz mono 16-bit PCM:
2068 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2069 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2070 */
2071 size += 0x1f;
2072 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002073
2074 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075}
2076
Ashish Jain5106d362016-05-11 19:23:33 +05302077static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2078{
2079 uint64_t actual_frames_rendered = 0;
2080 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2081
2082 /* This adjustment accounts for buffering after app processor.
2083 * It is based on estimated DSP latency per use case, rather than exact.
2084 */
2085 int64_t platform_latency = platform_render_latency(out->usecase) *
2086 out->sample_rate / 1000000LL;
2087
2088 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2089 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2090 * hence only estimate.
2091 */
2092 int64_t signed_frames = out->written - kernel_buffer_size;
2093
2094 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2095
2096 if (signed_frames > 0)
2097 actual_frames_rendered = signed_frames;
2098
2099 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2100 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2101 (long long int)out->written, (int)kernel_buffer_size,
2102 audio_bytes_per_sample(out->compr_config.codec->format),
2103 popcount(out->channel_mask));
2104
2105 return actual_frames_rendered;
2106}
2107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2109{
2110 struct stream_out *out = (struct stream_out *)stream;
2111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113}
2114
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002115static int out_set_sample_rate(struct audio_stream *stream __unused,
2116 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117{
2118 return -ENOSYS;
2119}
2120
2121static size_t out_get_buffer_size(const struct audio_stream *stream)
2122{
2123 struct stream_out *out = (struct stream_out *)stream;
2124
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002125 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002127 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2128 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002130 return out->config.period_size *
2131 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132}
2133
2134static uint32_t out_get_channels(const struct audio_stream *stream)
2135{
2136 struct stream_out *out = (struct stream_out *)stream;
2137
2138 return out->channel_mask;
2139}
2140
2141static audio_format_t out_get_format(const struct audio_stream *stream)
2142{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 struct stream_out *out = (struct stream_out *)stream;
2144
2145 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146}
2147
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002148static int out_set_format(struct audio_stream *stream __unused,
2149 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150{
2151 return -ENOSYS;
2152}
2153
2154static int out_standby(struct audio_stream *stream)
2155{
2156 struct stream_out *out = (struct stream_out *)stream;
2157 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302159 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2160 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002161 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2162 /* Ignore standby in case of voip call because the voip output
2163 * stream is closed in adev_close_output_stream()
2164 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302165 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002166 return 0;
2167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002169 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002171 if (adev->adm_deregister_stream)
2172 adev->adm_deregister_stream(adev->adm_data, out->handle);
2173
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002174 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002176 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 if (out->pcm) {
2178 pcm_close(out->pcm);
2179 out->pcm = NULL;
2180 }
2181 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002182 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302184 out->send_next_track_params = false;
2185 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002186 out->gapless_mdata.encoder_delay = 0;
2187 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002188 if (out->compr != NULL) {
2189 compress_close(out->compr);
2190 out->compr = NULL;
2191 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002192 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002194 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 }
2196 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302197 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 return 0;
2199}
2200
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002201static int out_dump(const struct audio_stream *stream __unused,
2202 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203{
2204 return 0;
2205}
2206
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002207static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2208{
2209 int ret = 0;
2210 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002211
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002212 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002213 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002214 return -EINVAL;
2215 }
2216
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302217 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002218
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002219 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2220 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302221 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002222 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002223 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2224 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302225 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002226 }
2227
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002228 ALOGV("%s new encoder delay %u and padding %u", __func__,
2229 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2230
2231 return 0;
2232}
2233
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002234static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2235{
2236 return out == adev->primary_output || out == adev->voice_tx_output;
2237}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2240{
2241 struct stream_out *out = (struct stream_out *)stream;
2242 struct audio_device *adev = out->dev;
2243 struct str_parms *parms;
2244 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002245 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246
sangwoobc677242013-08-08 16:53:43 +09002247 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002248 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302250 if (!parms)
2251 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002252 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2253 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002255 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002256 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002258 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002259 * When HDMI cable is unplugged the music playback is paused and
2260 * the policy manager sends routing=0. But the audioflinger continues
2261 * to write data until standby time (3sec). As the HDMI core is
2262 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002263 * Avoid this by routing audio to speaker until standby.
2264 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002265 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2266 (val == AUDIO_DEVICE_NONE) &&
2267 !audio_extn_dolby_is_passthrough_stream(out) &&
2268 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2269 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002270 }
2271
2272 /*
2273 * select_devices() call below switches all the usecases on the same
2274 * backend to the new device. Refer to check_usecases_codec_backend() in
2275 * the select_devices(). But how do we undo this?
2276 *
2277 * For example, music playback is active on headset (deep-buffer usecase)
2278 * and if we go to ringtones and select a ringtone, low-latency usecase
2279 * will be started on headset+speaker. As we can't enable headset+speaker
2280 * and headset devices at the same time, select_devices() switches the music
2281 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2282 * So when the ringtone playback is completed, how do we undo the same?
2283 *
2284 * We are relying on the out_set_parameters() call on deep-buffer output,
2285 * once the ringtone playback is ended.
2286 * NOTE: We should not check if the current devices are same as new devices.
2287 * Because select_devices() must be called to switch back the music
2288 * playback to headset.
2289 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002290 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002291 out->devices = val;
2292
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302293 if (!out->standby) {
2294 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2295 adev->perf_lock_opts,
2296 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002297 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302298 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2299 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002300
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002301 if (output_drives_call(adev, out)) {
2302 if(!voice_is_in_call(adev)) {
2303 if (adev->mode == AUDIO_MODE_IN_CALL) {
2304 adev->current_call_output = out;
2305 ret = voice_start_call(adev);
2306 }
2307 } else {
2308 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002309 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002310 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002311 }
2312 }
2313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002315 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002317
2318 if (out == adev->primary_output) {
2319 pthread_mutex_lock(&adev->lock);
2320 audio_extn_set_parameters(adev, parms);
2321 pthread_mutex_unlock(&adev->lock);
2322 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002323 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002324 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002325 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002326
2327 audio_extn_dts_create_state_notifier_node(out->usecase);
2328 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2329 popcount(out->channel_mask),
2330 out->playback_started);
2331
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002332 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002333 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302336error:
Eric Laurent994a6932013-07-17 11:51:42 -07002337 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 return ret;
2339}
2340
2341static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2342{
2343 struct stream_out *out = (struct stream_out *)stream;
2344 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002345 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 char value[256];
2347 struct str_parms *reply = str_parms_create();
2348 size_t i, j;
2349 int ret;
2350 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002351
2352 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002353 if (reply) {
2354 str_parms_destroy(reply);
2355 }
2356 if (query) {
2357 str_parms_destroy(query);
2358 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002359 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2360 return NULL;
2361 }
2362
Eric Laurent994a6932013-07-17 11:51:42 -07002363 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2365 if (ret >= 0) {
2366 value[0] = '\0';
2367 i = 0;
2368 while (out->supported_channel_masks[i] != 0) {
2369 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2370 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2371 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002372 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002374 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375 first = false;
2376 break;
2377 }
2378 }
2379 i++;
2380 }
2381 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2382 str = str_parms_to_str(reply);
2383 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002384 voice_extn_out_get_parameters(out, query, reply);
2385 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002386 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002387 free(str);
2388 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002389 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002391
Alexy Joseph62142aa2015-11-16 15:10:34 -08002392
2393 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2394 if (ret >= 0) {
2395 value[0] = '\0';
2396 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2397 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302398 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002399 } else {
2400 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302401 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002402 }
2403 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002404 if (str)
2405 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002406 str = str_parms_to_str(reply);
2407 }
2408
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002409 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2410 if (ret >= 0) {
2411 value[0] = '\0';
2412 i = 0;
2413 first = true;
2414 while (out->supported_formats[i] != 0) {
2415 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2416 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2417 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002418 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002419 }
2420 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2421 first = false;
2422 break;
2423 }
2424 }
2425 i++;
2426 }
2427 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002428 if (str)
2429 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002430 str = str_parms_to_str(reply);
2431 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002432
2433 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2434 if (ret >= 0) {
2435 value[0] = '\0';
2436 i = 0;
2437 first = true;
2438 while (out->supported_sample_rates[i] != 0) {
2439 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2440 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2441 if (!first) {
2442 strlcat(value, "|", sizeof(value));
2443 }
2444 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2445 first = false;
2446 break;
2447 }
2448 }
2449 i++;
2450 }
2451 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2452 if (str)
2453 free(str);
2454 str = str_parms_to_str(reply);
2455 }
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 str_parms_destroy(query);
2458 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002459 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return str;
2461}
2462
2463static uint32_t out_get_latency(const struct audio_stream_out *stream)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002466 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467
Alexy Josephaa54c872014-12-03 02:46:47 -08002468 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002469 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002470 } else {
2471 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002472 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002473 }
2474
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302475 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002476 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477}
2478
2479static int out_set_volume(struct audio_stream_out *stream, float left,
2480 float right)
2481{
Eric Laurenta9024de2013-04-04 09:19:12 -07002482 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002483 int volume[2];
2484
Eric Laurenta9024de2013-04-04 09:19:12 -07002485 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2486 /* only take left channel into account: the API is for stereo anyway */
2487 out->muted = (left == 0.0f);
2488 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002489 } else if (is_offload_usecase(out->usecase)) {
Mingming Yin21854652016-04-13 11:54:02 -07002490 if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002491 /*
2492 * Set mute or umute on HDMI passthrough stream.
2493 * Only take left channel into account.
2494 * Mute is 0 and unmute 1
2495 */
2496 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2497 } else {
2498 char mixer_ctl_name[128];
2499 struct audio_device *adev = out->dev;
2500 struct mixer_ctl *ctl;
2501 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002502 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002504 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2505 "Compress Playback %d Volume", pcm_device_id);
2506 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2507 if (!ctl) {
2508 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2509 __func__, mixer_ctl_name);
2510 return -EINVAL;
2511 }
2512 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2513 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2514 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2515 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002516 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002517 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 return -ENOSYS;
2520}
2521
2522static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2523 size_t bytes)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302527 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002528 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002530 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302531
Naresh Tanniru80659832014-06-04 18:17:56 +05302532 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002533
Ashish Jainbbce4322016-02-16 13:25:27 +05302534 if (is_offload_usecase(out->usecase)) {
2535 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302536 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2537 pthread_mutex_unlock(&out->lock);
2538 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302539 } else {
2540 /* increase written size during SSR to avoid mismatch
2541 * with the written frames count in AF
2542 */
2543 out->written += bytes / (out->config.channels * sizeof(short));
2544 ALOGD(" %s: sound card is not active/SSR state", __func__);
2545 ret= -EIO;
2546 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302547 }
2548 }
2549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002551 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002552 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002553 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2554 ret = voice_extn_compress_voip_start_output_stream(out);
2555 else
2556 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002557 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002558 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002560 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 goto exit;
2562 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002563
2564 if (last_known_cal_step != -1) {
2565 ALOGD("%s: retry previous failed cal level set", __func__);
2566 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2567 }
2568
vivek mehta446c3962015-09-14 10:57:35 -07002569 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002570 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572
Ashish Jain81eb2a82015-05-13 10:52:34 +05302573 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002574 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302575 adev->is_channel_status_set = true;
2576 }
2577
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002578 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002579 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002580 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002581 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002582 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2583 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302584 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2585 ALOGD("copl(%p):send next track params in gapless", out);
2586 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2587 out->send_next_track_params = false;
2588 out->is_compr_metadata_avail = false;
2589 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002590 }
2591
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002592 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302593 if (ret < 0)
2594 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302595 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002596 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302597 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302599 } else if (-ENETRESET == ret) {
2600 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2601 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2602 pthread_mutex_unlock(&out->lock);
2603 out_standby(&out->stream.common);
2604 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002605 }
Ashish Jain5106d362016-05-11 19:23:33 +05302606 if ( ret == (ssize_t)bytes && !out->non_blocking)
2607 out->written += bytes;
2608
Naresh Tanniru80659832014-06-04 18:17:56 +05302609 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002610 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002611 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002612 out->playback_started = 1;
2613 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002614
2615 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2616 popcount(out->channel_mask),
2617 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 }
2619 pthread_mutex_unlock(&out->lock);
2620 return ret;
2621 } else {
2622 if (out->pcm) {
2623 if (out->muted)
2624 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002625
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302626 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002627
2628 if (adev->adm_request_focus)
2629 adev->adm_request_focus(adev->adm_data, out->handle);
2630
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002631 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2632 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2633 else
2634 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002635
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302636 if (ret < 0)
2637 ret = -errno;
2638 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002639 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002640
2641 if (adev->adm_abandon_focus)
2642 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002643 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 }
2645
2646exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302647 /* ToDo: There may be a corner case when SSR happens back to back during
2648 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302649 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302650 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302651 }
2652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 pthread_mutex_unlock(&out->lock);
2654
2655 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002656 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002657 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302658 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302659 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302660 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302661 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302662 out->standby = true;
2663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302665 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302666 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 }
2668 return bytes;
2669}
2670
2671static int out_get_render_position(const struct audio_stream_out *stream,
2672 uint32_t *dsp_frames)
2673{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302675 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002676
2677 if (dsp_frames == NULL)
2678 return -EINVAL;
2679
2680 *dsp_frames = 0;
2681 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002682 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302683
2684 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2685 * this operation and adev_close_output_stream(where out gets reset).
2686 */
2687 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2688 *dsp_frames = get_actual_pcm_frames_rendered(out);
2689 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2690 return 0;
2691 }
2692
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002693 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302694 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302695 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002696 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302697 if (ret < 0)
2698 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002699 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302700 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 }
2702 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302703 if (-ENETRESET == ret) {
2704 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2705 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2706 return -EINVAL;
2707 } else if(ret < 0) {
2708 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2709 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302710 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2711 /*
2712 * Handle corner case where compress session is closed during SSR
2713 * and timestamp is queried
2714 */
2715 ALOGE(" ERROR: sound card not active, return error");
2716 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302717 } else {
2718 return 0;
2719 }
Zhou Song32a556e2015-05-05 10:46:56 +08002720 } else if (audio_is_linear_pcm(out->format)) {
2721 *dsp_frames = out->written;
2722 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002723 } else
2724 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725}
2726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002727static int out_add_audio_effect(const struct audio_stream *stream __unused,
2728 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
2730 return 0;
2731}
2732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002733static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2734 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735{
2736 return 0;
2737}
2738
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002739static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2740 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741{
2742 return -EINVAL;
2743}
2744
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002745static int out_get_presentation_position(const struct audio_stream_out *stream,
2746 uint64_t *frames, struct timespec *timestamp)
2747{
2748 struct stream_out *out = (struct stream_out *)stream;
2749 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002750 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002751
Ashish Jain5106d362016-05-11 19:23:33 +05302752 /* below piece of code is not guarded against any lock because audioFliner serializes
2753 * this operation and adev_close_output_stream( where out gets reset).
2754 */
2755 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2756 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2757 *frames = get_actual_pcm_frames_rendered(out);
2758 /* this is the best we can do */
2759 clock_gettime(CLOCK_MONOTONIC, timestamp);
2760 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2761 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2762 return 0;
2763 }
2764
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002765 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002766
Ashish Jain5106d362016-05-11 19:23:33 +05302767 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2768 ret = compress_get_tstamp(out->compr, &dsp_frames,
2769 &out->sample_rate);
2770 ALOGVV("%s rendered frames %ld sample_rate %d",
2771 __func__, dsp_frames, out->sample_rate);
2772 *frames = dsp_frames;
2773 if (ret < 0)
2774 ret = -errno;
2775 if (-ENETRESET == ret) {
2776 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2777 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2778 ret = -EINVAL;
2779 } else
2780 ret = 0;
2781 /* this is the best we can do */
2782 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002783 } else {
2784 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002785 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002786 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2787 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002788 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002789 // This adjustment accounts for buffering after app processor.
2790 // It is based on estimated DSP latency per use case, rather than exact.
2791 signed_frames -=
2792 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2793
Eric Laurent949a0892013-09-20 09:20:13 -07002794 // It would be unusual for this value to be negative, but check just in case ...
2795 if (signed_frames >= 0) {
2796 *frames = signed_frames;
2797 ret = 0;
2798 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002799 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302800 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2801 *frames = out->written;
2802 clock_gettime(CLOCK_MONOTONIC, timestamp);
2803 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002804 }
2805 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002806 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002807 return ret;
2808}
2809
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002810static int out_set_callback(struct audio_stream_out *stream,
2811 stream_callback_t callback, void *cookie)
2812{
2813 struct stream_out *out = (struct stream_out *)stream;
2814
2815 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002816 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 out->offload_callback = callback;
2818 out->offload_cookie = cookie;
2819 pthread_mutex_unlock(&out->lock);
2820 return 0;
2821}
2822
2823static int out_pause(struct audio_stream_out* stream)
2824{
2825 struct stream_out *out = (struct stream_out *)stream;
2826 int status = -ENOSYS;
2827 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002828 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002829 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002830 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002831 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302832 struct audio_device *adev = out->dev;
2833 int snd_scard_state = get_snd_card_state(adev);
2834
2835 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2836 status = compress_pause(out->compr);
2837
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002839
Mingming Yin21854652016-04-13 11:54:02 -07002840 if (audio_extn_passthru_is_active()) {
2841 ALOGV("offload use case, pause passthru");
2842 audio_extn_passthru_on_pause(out);
2843 }
2844
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302845 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002846 audio_extn_dts_notify_playback_state(out->usecase, 0,
2847 out->sample_rate, popcount(out->channel_mask),
2848 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 }
2850 pthread_mutex_unlock(&out->lock);
2851 }
2852 return status;
2853}
2854
2855static int out_resume(struct audio_stream_out* stream)
2856{
2857 struct stream_out *out = (struct stream_out *)stream;
2858 int status = -ENOSYS;
2859 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002860 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002861 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002863 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302865 struct audio_device *adev = out->dev;
2866 int snd_scard_state = get_snd_card_state(adev);
2867
Mingming Yin21854652016-04-13 11:54:02 -07002868 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2869 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2870 pthread_mutex_lock(&out->dev->lock);
2871 ALOGV("offload resume, check and set hdmi backend again");
2872 check_and_set_hdmi_backend(out);
2873 pthread_mutex_unlock(&out->dev->lock);
2874 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302875 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002876 }
2877 if (!status) {
2878 out->offload_state = OFFLOAD_STATE_PLAYING;
2879 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302880 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002881 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2882 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 }
2884 pthread_mutex_unlock(&out->lock);
2885 }
2886 return status;
2887}
2888
2889static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2890{
2891 struct stream_out *out = (struct stream_out *)stream;
2892 int status = -ENOSYS;
2893 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002894 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002895 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2897 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2898 else
2899 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2900 pthread_mutex_unlock(&out->lock);
2901 }
2902 return status;
2903}
2904
2905static int out_flush(struct audio_stream_out* stream)
2906{
2907 struct stream_out *out = (struct stream_out *)stream;
2908 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002909 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002910 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002911 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302913 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002915 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 return 0;
2917 }
2918 return -ENOSYS;
2919}
2920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921/** audio_stream_in implementation **/
2922static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2923{
2924 struct stream_in *in = (struct stream_in *)stream;
2925
2926 return in->config.rate;
2927}
2928
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002929static int in_set_sample_rate(struct audio_stream *stream __unused,
2930 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931{
2932 return -ENOSYS;
2933}
2934
2935static size_t in_get_buffer_size(const struct audio_stream *stream)
2936{
2937 struct stream_in *in = (struct stream_in *)stream;
2938
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002939 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2940 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002941 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2942 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002943
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002944 return in->config.period_size *
2945 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946}
2947
2948static uint32_t in_get_channels(const struct audio_stream *stream)
2949{
2950 struct stream_in *in = (struct stream_in *)stream;
2951
2952 return in->channel_mask;
2953}
2954
2955static audio_format_t in_get_format(const struct audio_stream *stream)
2956{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002957 struct stream_in *in = (struct stream_in *)stream;
2958
2959 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960}
2961
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002962static int in_set_format(struct audio_stream *stream __unused,
2963 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964{
2965 return -ENOSYS;
2966}
2967
2968static int in_standby(struct audio_stream *stream)
2969{
2970 struct stream_in *in = (struct stream_in *)stream;
2971 struct audio_device *adev = in->dev;
2972 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302973 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2974 stream, in->usecase, use_case_table[in->usecase]);
2975
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002976 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2977 /* Ignore standby in case of voip call because the voip input
2978 * stream is closed in adev_close_input_stream()
2979 */
2980 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2981 return status;
2982 }
2983
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002984 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002985 if (!in->standby && in->is_st_session) {
2986 ALOGD("%s: sound trigger pcm stop lab", __func__);
2987 audio_extn_sound_trigger_stop_lab(in);
2988 in->standby = 1;
2989 }
2990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002992 if (adev->adm_deregister_stream)
2993 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2994
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002995 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002997 if (in->pcm) {
2998 pcm_close(in->pcm);
2999 in->pcm = NULL;
3000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003002 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 }
3004 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003005 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 return status;
3007}
3008
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003009static int in_dump(const struct audio_stream *stream __unused,
3010 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011{
3012 return 0;
3013}
3014
3015static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3016{
3017 struct stream_in *in = (struct stream_in *)stream;
3018 struct audio_device *adev = in->dev;
3019 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003021 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303023 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 parms = str_parms_create_str(kvpairs);
3025
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303026 if (!parms)
3027 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003028 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003029 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003030
3031 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3032 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 val = atoi(value);
3034 /* no audio source uses val == 0 */
3035 if ((in->source != val) && (val != 0)) {
3036 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003037 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3038 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3039 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003040 (in->config.rate == 8000 || in->config.rate == 16000 ||
3041 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003042 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003043 err = voice_extn_compress_voip_open_input_stream(in);
3044 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003045 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003046 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003047 }
3048 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 }
3050 }
3051
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003052 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3053 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003055 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 in->device = val;
3057 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003058 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003059 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 }
3061 }
3062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003064 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065
3066 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303067error:
Eric Laurent994a6932013-07-17 11:51:42 -07003068 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 return ret;
3070}
3071
3072static char* in_get_parameters(const struct audio_stream *stream,
3073 const char *keys)
3074{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 struct stream_in *in = (struct stream_in *)stream;
3076 struct str_parms *query = str_parms_create_str(keys);
3077 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003079
3080 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003081 if (reply) {
3082 str_parms_destroy(reply);
3083 }
3084 if (query) {
3085 str_parms_destroy(query);
3086 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003087 ALOGE("in_get_parameters: failed to create query or reply");
3088 return NULL;
3089 }
3090
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003091 ALOGV("%s: enter: keys - %s", __func__, keys);
3092
3093 voice_extn_in_get_parameters(in, query, reply);
3094
3095 str = str_parms_to_str(reply);
3096 str_parms_destroy(query);
3097 str_parms_destroy(reply);
3098
3099 ALOGV("%s: exit: returns - %s", __func__, str);
3100 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101}
3102
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003103static int in_set_gain(struct audio_stream_in *stream __unused,
3104 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105{
3106 return 0;
3107}
3108
3109static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3110 size_t bytes)
3111{
3112 struct stream_in *in = (struct stream_in *)stream;
3113 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303114 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303115 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303116 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003118 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303119
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003120 if (in->is_st_session) {
3121 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3122 /* Read from sound trigger HAL */
3123 audio_extn_sound_trigger_read(in, buffer, bytes);
3124 pthread_mutex_unlock(&in->lock);
3125 return bytes;
3126 }
3127
Ashish Jainbbce4322016-02-16 13:25:27 +05303128 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003129 ALOGD(" %s: sound card is not active/SSR state", __func__);
3130 ret= -EIO;;
3131 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132 }
3133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003135 pthread_mutex_lock(&adev->lock);
3136 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3137 ret = voice_extn_compress_voip_start_input_stream(in);
3138 else
3139 ret = start_input_stream(in);
3140 pthread_mutex_unlock(&adev->lock);
3141 if (ret != 0) {
3142 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 }
3144 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003145 if (adev->adm_register_input_stream)
3146 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003149 if (adev->adm_request_focus)
3150 adev->adm_request_focus(adev->adm_data, in->capture_handle);
3151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303153 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003154 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303155 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003156 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303157 } else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003158 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303159 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003160 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303161 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3162 if (bytes % 4 == 0) {
3163 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3164 int_buf_stream = buffer;
3165 for (size_t itt=0; itt < bytes/4 ; itt++) {
3166 int_buf_stream[itt] >>= 8;
3167 }
3168 } else {
3169 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3170 ret = -EINVAL;
3171 goto exit;
3172 }
3173 } if (ret < 0) {
3174 ret = -errno;
3175 }
3176 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 }
3178
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003179 if (adev->adm_abandon_focus)
3180 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
3181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 /*
3183 * Instead of writing zeroes here, we could trust the hardware
3184 * to always provide zeroes when muted.
3185 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303186 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3187 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188 memset(buffer, 0, bytes);
3189
3190exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303191 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303192 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003193 if (-ENETRESET == ret)
3194 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196 pthread_mutex_unlock(&in->lock);
3197
3198 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303199 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303200 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303201 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303202 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303203 in->standby = true;
3204 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303205 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003207 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303208 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303209 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210 }
3211 return bytes;
3212}
3213
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003214static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215{
3216 return 0;
3217}
3218
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003219static int add_remove_audio_effect(const struct audio_stream *stream,
3220 effect_handle_t effect,
3221 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003223 struct stream_in *in = (struct stream_in *)stream;
3224 int status = 0;
3225 effect_descriptor_t desc;
3226
3227 status = (*effect)->get_descriptor(effect, &desc);
3228 if (status != 0)
3229 return status;
3230
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003231 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003232 pthread_mutex_lock(&in->dev->lock);
3233 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3234 in->enable_aec != enable &&
3235 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3236 in->enable_aec = enable;
3237 if (!in->standby)
3238 select_devices(in->dev, in->usecase);
3239 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003240 if (in->enable_ns != enable &&
3241 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3242 in->enable_ns = enable;
3243 if (!in->standby)
3244 select_devices(in->dev, in->usecase);
3245 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003246 pthread_mutex_unlock(&in->dev->lock);
3247 pthread_mutex_unlock(&in->lock);
3248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 return 0;
3250}
3251
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003252static int in_add_audio_effect(const struct audio_stream *stream,
3253 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254{
Eric Laurent994a6932013-07-17 11:51:42 -07003255 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003256 return add_remove_audio_effect(stream, effect, true);
3257}
3258
3259static int in_remove_audio_effect(const struct audio_stream *stream,
3260 effect_handle_t effect)
3261{
Eric Laurent994a6932013-07-17 11:51:42 -07003262 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003263 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264}
3265
3266static int adev_open_output_stream(struct audio_hw_device *dev,
3267 audio_io_handle_t handle,
3268 audio_devices_t devices,
3269 audio_output_flags_t flags,
3270 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003271 struct audio_stream_out **stream_out,
3272 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273{
3274 struct audio_device *adev = (struct audio_device *)dev;
3275 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303276 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003277 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303280
3281 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3282 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003283 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303284 return -EINVAL;
3285 }
3286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3288
Mingming Yin3a941d42016-02-17 18:08:05 -08003289 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3290 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303291 devices, flags, &out->stream);
3292
3293
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003294 if (!out) {
3295 return -ENOMEM;
3296 }
3297
Haynes Mathew George204045b2015-02-25 20:32:03 -08003298 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003299 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003300 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 if (devices == AUDIO_DEVICE_NONE)
3303 devices = AUDIO_DEVICE_OUT_SPEAKER;
3304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305 out->flags = flags;
3306 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003307 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003308 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 out->sample_rate = config->sample_rate;
3310 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3311 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003312 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003313 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003314 out->non_blocking = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315
Mingming Yin3a941d42016-02-17 18:08:05 -08003316 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3317 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3318 pthread_mutex_lock(&adev->lock);
3319 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3320 ret = read_hdmi_sink_caps(out);
3321 pthread_mutex_unlock(&adev->lock);
3322 if (ret != 0) {
3323 if (ret == -ENOSYS) {
3324 /* ignore and go with default */
3325 ret = 0;
3326 } else {
3327 ALOGE("error reading hdmi sink caps");
3328 goto error_open;
3329 }
3330 }
3331 }
3332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003334 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303335 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3336 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003337 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3338 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3339
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003340 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003341 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3342 /*
3343 * Do not handle stereo output in Multi-channel cases
3344 * Stereo case is handled in normal playback path
3345 */
3346 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3347 ret = AUDIO_CHANNEL_OUT_STEREO;
3348 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003349
3350 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3351 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003352 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003353 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003354 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003355
3356 if (config->sample_rate == 0)
3357 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3358 if (config->channel_mask == 0)
3359 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003360 if (config->format == 0)
3361 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003362
3363 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003364 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003365 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3367 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003369 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003371 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3372 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003373 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003374 ret = voice_extn_compress_voip_open_output_stream(out);
3375 if (ret != 0) {
3376 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3377 __func__, ret);
3378 goto error_open;
3379 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003380 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3381 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003383 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3384 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3385 ALOGE("%s: Unsupported Offload information", __func__);
3386 ret = -EINVAL;
3387 goto error_open;
3388 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003389
Mingming Yin3a941d42016-02-17 18:08:05 -08003390 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003391 if(config->offload_info.format == 0)
3392 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003393 if (config->offload_info.sample_rate == 0)
3394 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003395 }
3396
Mingming Yin90310102013-11-13 16:57:00 -08003397 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003398 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003399 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003400 ret = -EINVAL;
3401 goto error_open;
3402 }
3403
3404 out->compr_config.codec = (struct snd_codec *)
3405 calloc(1, sizeof(struct snd_codec));
3406
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003407 if (!out->compr_config.codec) {
3408 ret = -ENOMEM;
3409 goto error_open;
3410 }
3411
vivek mehta0ea887a2015-08-26 14:01:20 -07003412 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303413 out->stream.pause = out_pause;
3414 out->stream.flush = out_flush;
3415 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003416 out->usecase = get_offload_usecase(adev, true);
3417 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003418 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003419 out->stream.set_callback = out_set_callback;
3420 out->stream.pause = out_pause;
3421 out->stream.resume = out_resume;
3422 out->stream.drain = out_drain;
3423 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003424 out->usecase = get_offload_usecase(adev, false);
3425 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003426 }
vivek mehta446c3962015-09-14 10:57:35 -07003427
3428 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003429 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3430 config->format == 0 && config->sample_rate == 0 &&
3431 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003432 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003433 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3434 } else {
3435 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3436 ret = -EEXIST;
3437 goto error_open;
3438 }
vivek mehta446c3962015-09-14 10:57:35 -07003439 }
3440
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 if (config->offload_info.channel_mask)
3442 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003443 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003444 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003445 config->offload_info.channel_mask = config->channel_mask;
3446 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003447 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 out->sample_rate = config->offload_info.sample_rate;
3449
Mingming Yin3ee55c62014-08-04 14:23:35 -07003450 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003451
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003452 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003453 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003454 audio_extn_dolby_get_snd_codec_id(adev, out,
3455 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003456 else
3457 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003458 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003459
Ashish Jain5106d362016-05-11 19:23:33 +05303460 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003461 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003462 platform_get_pcm_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303463 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
Mingming Yin21854652016-04-13 11:54:02 -07003464 } else if (audio_extn_dolby_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003465 out->compr_config.fragment_size =
3466 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303467 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003468 } else {
3469 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003470 platform_get_compress_offload_buffer_size(&config->offload_info);
Ashish Jain5106d362016-05-11 19:23:33 +05303471 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003472 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003473 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003474 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003475 out->compr_config.codec->bit_rate =
3476 config->offload_info.bit_rate;
3477 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003478 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303480 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003481 /*TODO: Do we need to change it for passthrough */
3482 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483
Manish Dewangana6fc5442015-08-24 20:30:31 +05303484 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3485 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3486 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3487 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
vivek mehta0ea887a2015-08-26 14:01:20 -07003488 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3489 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Ashish Jain5106d362016-05-11 19:23:33 +05303490 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
3491 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
3492 if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
Mingming Yin3ee55c62014-08-04 14:23:35 -07003493 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003494
Amit Shekhar6f461b12014-08-01 14:52:58 -07003495 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303496 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003497
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3499 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003500
Alexy Josephaa54c872014-12-03 02:46:47 -08003501
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003502 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303503 out->send_next_track_params = false;
3504 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003505 out->offload_state = OFFLOAD_STATE_IDLE;
3506 out->playback_started = 0;
3507
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003508 audio_extn_dts_create_state_notifier_node(out->usecase);
3509
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 create_offload_callback_thread(out);
3511 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3512 __func__, config->offload_info.version,
3513 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303514
3515 /* Disable gapless if any of the following is true
3516 * passthrough playback
3517 * AV playback
3518 * Direct PCM playback
3519 */
3520 if (audio_extn_dolby_is_passthrough_stream(out) ||
3521 config->offload_info.has_video ||
3522 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3523 check_and_set_gapless_mode(adev, false);
3524 } else
3525 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003526
3527 if (audio_extn_dolby_is_passthrough_stream(out)) {
3528 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3529 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003530 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303531 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003532 if (ret != 0) {
3533 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3534 __func__, ret);
3535 goto error_open;
3536 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003537 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3538 if (config->sample_rate == 0)
3539 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3540 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3541 config->sample_rate != 8000) {
3542 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3543 ret = -EINVAL;
3544 goto error_open;
3545 }
3546 out->sample_rate = config->sample_rate;
3547 out->config.rate = config->sample_rate;
3548 if (config->format == AUDIO_FORMAT_DEFAULT)
3549 config->format = AUDIO_FORMAT_PCM_16_BIT;
3550 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3551 config->format = AUDIO_FORMAT_PCM_16_BIT;
3552 ret = -EINVAL;
3553 goto error_open;
3554 }
3555 out->format = config->format;
3556 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3557 out->config = pcm_config_afe_proxy_playback;
3558 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003559 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3560 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3561 out->config = pcm_config_low_latency;
3562 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003563 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003564 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3566 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003568 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3569 format = AUDIO_FORMAT_PCM_16_BIT;
3570 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3571 out->config = pcm_config_deep_buffer;
3572 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003573 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003574 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003575 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003576 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003577 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003578 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 }
3580
Mingming Yin21854652016-04-13 11:54:02 -07003581 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d out->flags:%x, flags:%x",
3582 __func__, devices, flags, format, out->sample_rate, out->bit_width, out->flags, flags);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003583 /* TODO remove this hardcoding and check why width is zero*/
3584 if (out->bit_width == 0)
3585 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003586 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3587 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003588 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303589 out->bit_width, out->channel_mask,
3590 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003591 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3592 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3593 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003594 if(adev->primary_output == NULL)
3595 adev->primary_output = out;
3596 else {
3597 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003598 ret = -EEXIST;
3599 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003600 }
3601 }
3602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 /* Check if this usecase is already existing */
3604 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003605 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3606 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003609 ret = -EEXIST;
3610 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 }
3612 pthread_mutex_unlock(&adev->lock);
3613
3614 out->stream.common.get_sample_rate = out_get_sample_rate;
3615 out->stream.common.set_sample_rate = out_set_sample_rate;
3616 out->stream.common.get_buffer_size = out_get_buffer_size;
3617 out->stream.common.get_channels = out_get_channels;
3618 out->stream.common.get_format = out_get_format;
3619 out->stream.common.set_format = out_set_format;
3620 out->stream.common.standby = out_standby;
3621 out->stream.common.dump = out_dump;
3622 out->stream.common.set_parameters = out_set_parameters;
3623 out->stream.common.get_parameters = out_get_parameters;
3624 out->stream.common.add_audio_effect = out_add_audio_effect;
3625 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3626 out->stream.get_latency = out_get_latency;
3627 out->stream.set_volume = out_set_volume;
3628 out->stream.write = out_write;
3629 out->stream.get_render_position = out_get_render_position;
3630 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003631 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003634 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003635 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
3637 config->format = out->stream.common.get_format(&out->stream.common);
3638 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3639 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3640
3641 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303642 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003643 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003644
3645 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3646 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3647 popcount(out->channel_mask), out->playback_started);
3648
Eric Laurent994a6932013-07-17 11:51:42 -07003649 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003651
3652error_open:
3653 free(out);
3654 *stream_out = NULL;
3655 ALOGD("%s: exit: ret %d", __func__, ret);
3656 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657}
3658
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003659static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 struct audio_stream_out *stream)
3661{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 struct stream_out *out = (struct stream_out *)stream;
3663 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003664 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303666 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3667
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003668 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303669 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003670 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303671 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003672 if(ret != 0)
3673 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3674 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003675 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003676 out_standby(&stream->common);
3677
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003678 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003679 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003680 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003681 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 if (out->compr_config.codec != NULL)
3683 free(out->compr_config.codec);
3684 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003685
3686 if (adev->voice_tx_output == out)
3687 adev->voice_tx_output = NULL;
3688
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003689 pthread_cond_destroy(&out->cond);
3690 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003692 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693}
3694
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003695static void close_compress_sessions(struct audio_device *adev)
3696{
Mingming Yin7b762e72015-03-04 13:47:32 -08003697 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303698 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003699 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003700 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303701
3702 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003703 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303704 if (is_offload_usecase(usecase->id)) {
3705 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003706 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3707 out = usecase->stream.out;
3708 pthread_mutex_unlock(&adev->lock);
3709 out_standby(&out->stream.common);
3710 pthread_mutex_lock(&adev->lock);
3711 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303712 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003713 }
3714 pthread_mutex_unlock(&adev->lock);
3715}
3716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3718{
3719 struct audio_device *adev = (struct audio_device *)dev;
3720 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003722 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003723 int ret;
3724 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003726 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303729 if (!parms)
3730 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003731 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3732 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303733 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303734 if (strstr(snd_card_status, "OFFLINE")) {
3735 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303736 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003737 //close compress sessions on OFFLINE status
3738 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303739 } else if (strstr(snd_card_status, "ONLINE")) {
3740 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303741 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003742 //send dts hpx license if enabled
3743 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303744 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303745 }
3746
3747 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003748 status = voice_set_parameters(adev, parms);
3749 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003750 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003752 status = platform_set_parameters(adev->platform, parms);
3753 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003754 goto done;
3755
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003756 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3757 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003758 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3760 adev->bluetooth_nrec = true;
3761 else
3762 adev->bluetooth_nrec = false;
3763 }
3764
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003765 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3766 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3768 adev->screen_off = false;
3769 else
3770 adev->screen_off = true;
3771 }
3772
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003773 ret = str_parms_get_int(parms, "rotation", &val);
3774 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003775 bool reverse_speakers = false;
3776 switch(val) {
3777 // FIXME: note that the code below assumes that the speakers are in the correct placement
3778 // relative to the user when the device is rotated 90deg from its default rotation. This
3779 // assumption is device-specific, not platform-specific like this code.
3780 case 270:
3781 reverse_speakers = true;
3782 break;
3783 case 0:
3784 case 90:
3785 case 180:
3786 break;
3787 default:
3788 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003789 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003790 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003791 if (status == 0) {
3792 if (adev->speaker_lr_swap != reverse_speakers) {
3793 adev->speaker_lr_swap = reverse_speakers;
3794 // only update the selected device if there is active pcm playback
3795 struct audio_usecase *usecase;
3796 struct listnode *node;
3797 list_for_each(node, &adev->usecase_list) {
3798 usecase = node_to_item(node, struct audio_usecase, list);
3799 if (usecase->type == PCM_PLAYBACK) {
3800 select_devices(adev, usecase->id);
3801 break;
3802 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003803 }
3804 }
3805 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003806 }
3807
Mingming Yin514a8bc2014-07-29 15:22:21 -07003808 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3809 if (ret >= 0) {
3810 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3811 adev->bt_wb_speech_enabled = true;
3812 else
3813 adev->bt_wb_speech_enabled = false;
3814 }
3815
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003816 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3817 if (ret >= 0) {
3818 val = atoi(value);
3819 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3820 ALOGV("cache new edid");
3821 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003822 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3823 /*
3824 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3825 * Per AudioPolicyManager, USB device is higher priority than WFD.
3826 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3827 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3828 * starting voice call on USB
3829 */
3830 ALOGV("detected USB connect .. disable proxy");
3831 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003832 }
3833 }
3834
3835 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3836 if (ret >= 0) {
3837 val = atoi(value);
3838 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3839 ALOGV("invalidate cached edid");
3840 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003841 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3842 ALOGV("detected USB disconnect .. enable proxy");
3843 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003844 }
3845 }
3846
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003847 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003848
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003849done:
3850 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003851 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303852error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003853 ALOGV("%s: exit with code(%d)", __func__, status);
3854 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855}
3856
3857static char* adev_get_parameters(const struct audio_hw_device *dev,
3858 const char *keys)
3859{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003860 struct audio_device *adev = (struct audio_device *)dev;
3861 struct str_parms *reply = str_parms_create();
3862 struct str_parms *query = str_parms_create_str(keys);
3863 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303864 char value[256] = {0};
3865 int ret = 0;
3866
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003867 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003868 if (reply) {
3869 str_parms_destroy(reply);
3870 }
3871 if (query) {
3872 str_parms_destroy(query);
3873 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003874 ALOGE("adev_get_parameters: failed to create query or reply");
3875 return NULL;
3876 }
3877
Naresh Tannirud7205b62014-06-20 02:54:48 +05303878 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3879 sizeof(value));
3880 if (ret >=0) {
3881 int val = 1;
3882 pthread_mutex_lock(&adev->snd_card_status.lock);
3883 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3884 val = 0;
3885 pthread_mutex_unlock(&adev->snd_card_status.lock);
3886 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3887 goto exit;
3888 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003889
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003890 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003891 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003892 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003893 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303894 pthread_mutex_unlock(&adev->lock);
3895
Naresh Tannirud7205b62014-06-20 02:54:48 +05303896exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003897 str = str_parms_to_str(reply);
3898 str_parms_destroy(query);
3899 str_parms_destroy(reply);
3900
3901 ALOGV("%s: exit: returns - %s", __func__, str);
3902 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903}
3904
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003905static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906{
3907 return 0;
3908}
3909
3910static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3911{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003912 int ret;
3913 struct audio_device *adev = (struct audio_device *)dev;
3914 pthread_mutex_lock(&adev->lock);
3915 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003916 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003917 pthread_mutex_unlock(&adev->lock);
3918 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919}
3920
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003921static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3922 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923{
3924 return -ENOSYS;
3925}
3926
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003927static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3928 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929{
3930 return -ENOSYS;
3931}
3932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003933static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3934 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935{
3936 return -ENOSYS;
3937}
3938
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003939static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3940 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941{
3942 return -ENOSYS;
3943}
3944
3945static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3946{
3947 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 pthread_mutex_lock(&adev->lock);
3950 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003951 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003953 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003954 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003955 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003956 adev->current_call_output = NULL;
3957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958 }
3959 pthread_mutex_unlock(&adev->lock);
3960 return 0;
3961}
3962
3963static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3964{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003965 int ret;
3966
3967 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003968 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003969 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3970 pthread_mutex_unlock(&adev->lock);
3971
3972 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973}
3974
3975static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3976{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003977 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978 return 0;
3979}
3980
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003981static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 const struct audio_config *config)
3983{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003984 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003986 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3987 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988}
3989
3990static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003991 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992 audio_devices_t devices,
3993 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003994 struct audio_stream_in **stream_in,
3995 audio_input_flags_t flags __unused,
3996 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003997 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998{
3999 struct audio_device *adev = (struct audio_device *)dev;
4000 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004001 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004002 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004003 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304006 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4007 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010
4011 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004012
4013 if (!in) {
4014 ALOGE("failed to allocate input stream");
4015 return -ENOMEM;
4016 }
4017
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304018 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304019 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4020 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004021 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004022 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 in->stream.common.get_sample_rate = in_get_sample_rate;
4025 in->stream.common.set_sample_rate = in_set_sample_rate;
4026 in->stream.common.get_buffer_size = in_get_buffer_size;
4027 in->stream.common.get_channels = in_get_channels;
4028 in->stream.common.get_format = in_get_format;
4029 in->stream.common.set_format = in_set_format;
4030 in->stream.common.standby = in_standby;
4031 in->stream.common.dump = in_dump;
4032 in->stream.common.set_parameters = in_set_parameters;
4033 in->stream.common.get_parameters = in_get_parameters;
4034 in->stream.common.add_audio_effect = in_add_audio_effect;
4035 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4036 in->stream.set_gain = in_set_gain;
4037 in->stream.read = in_read;
4038 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4039
4040 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004041 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043 in->standby = 1;
4044 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004045 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004046 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047
4048 /* Update config params with the requested sample rate and channels */
4049 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004050 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4051 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4052 is_low_latency = true;
4053#if LOW_LATENCY_CAPTURE_USE_CASE
4054 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4055#endif
4056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004059 in->format = config->format;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304060 in->bit_width = 16;
4061 in->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004063 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304064 if (adev->mode != AUDIO_MODE_IN_CALL) {
4065 ret = -EINVAL;
4066 goto err_open;
4067 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004068 if (config->sample_rate == 0)
4069 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4070 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4071 config->sample_rate != 8000) {
4072 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4073 ret = -EINVAL;
4074 goto err_open;
4075 }
4076 if (config->format == AUDIO_FORMAT_DEFAULT)
4077 config->format = AUDIO_FORMAT_PCM_16_BIT;
4078 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4079 config->format = AUDIO_FORMAT_PCM_16_BIT;
4080 ret = -EINVAL;
4081 goto err_open;
4082 }
4083
4084 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4085 in->config = pcm_config_afe_proxy_record;
4086 in->config.channels = channel_count;
4087 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304088 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304089 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4090 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004091 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004092 audio_extn_compr_cap_format_supported(config->format) &&
4093 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004094 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004095 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304096 /* restrict 24 bit capture for unprocessed source only
4097 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4098 */
4099 if (config->format == AUDIO_FORMAT_DEFAULT) {
4100 config->format = AUDIO_FORMAT_PCM_16_BIT;
4101 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4102 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4103 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4104 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4105 bool ret_error = false;
4106 in->bit_width = 24;
4107 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4108 from HAL is 24_packed and 8_24
4109 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4110 24_packed return error indicating supported format is 24_packed
4111 *> In case of any other source requesting 24 bit or float return error
4112 indicating format supported is 16 bit only.
4113
4114 on error flinger will retry with supported format passed
4115 */
4116 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4117 (source != AUDIO_SOURCE_CAMCORDER)) {
4118 config->format = AUDIO_FORMAT_PCM_16_BIT;
4119 if( config->sample_rate > 48000)
4120 config->sample_rate = 48000;
4121 ret_error = true;
4122 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4123 in->config.format = PCM_FORMAT_S24_3LE;
4124 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4125 in->config.format = PCM_FORMAT_S24_LE;
4126 } else {
4127 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4128 ret_error = true;
4129 }
4130
4131 if (ret_error) {
4132 ret = -EINVAL;
4133 goto err_open;
4134 }
4135 }
4136
4137 in->format = config->format;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004138 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004139 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004140 buffer_size = get_input_buffer_size(config->sample_rate,
4141 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004142 channel_count,
4143 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004144 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004145 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4146 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4147 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004148 (in->config.rate == 8000 || in->config.rate == 16000 ||
4149 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004150 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4151 voice_extn_compress_voip_open_input_stream(in);
4152 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004155 /* This stream could be for sound trigger lab,
4156 get sound trigger pcm if present */
4157 audio_extn_sound_trigger_check_and_get_session(in);
4158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004160 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004161 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162
4163err_open:
4164 free(in);
4165 *stream_in = NULL;
4166 return ret;
4167}
4168
4169static void adev_close_input_stream(struct audio_hw_device *dev,
4170 struct audio_stream_in *stream)
4171{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004172 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004173 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004174 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304175
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304176 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004177
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304178 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004179 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304180
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004181 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304182 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004183 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304184 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004185 if (ret != 0)
4186 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4187 __func__, ret);
4188 } else
4189 in_standby(&stream->common);
4190
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004191 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004192 audio_extn_ssr_deinit();
4193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194
Mingming Yine62d7842013-10-25 16:26:03 -07004195 if(audio_extn_compr_cap_enabled() &&
4196 audio_extn_compr_cap_format_supported(in->config.format))
4197 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004198
Mingming Yinfd7607b2016-01-22 12:48:44 -08004199 if (in->is_st_session) {
4200 ALOGV("%s: sound trigger pcm stop lab", __func__);
4201 audio_extn_sound_trigger_stop_lab(in);
4202 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004203 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 return;
4205}
4206
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004207static int adev_dump(const audio_hw_device_t *device __unused,
4208 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209{
4210 return 0;
4211}
4212
4213static int adev_close(hw_device_t *device)
4214{
4215 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004216
4217 if (!adev)
4218 return 0;
4219
4220 pthread_mutex_lock(&adev_init_lock);
4221
4222 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004223 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004224 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004225 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004226 audio_route_free(adev->audio_route);
4227 free(adev->snd_dev_ref_cnt);
4228 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004229 if (adev->adm_deinit)
4230 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004231 free(device);
4232 adev = NULL;
4233 }
4234 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 return 0;
4237}
4238
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004239/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4240 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4241 * just that it _might_ work.
4242 */
4243static int period_size_is_plausible_for_low_latency(int period_size)
4244{
4245 switch (period_size) {
4246 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004247 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004248 case 240:
4249 case 320:
4250 case 480:
4251 return 1;
4252 default:
4253 return 0;
4254 }
4255}
4256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257static int adev_open(const hw_module_t *module, const char *name,
4258 hw_device_t **device)
4259{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004260 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004261 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4262
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004263 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004264 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004265 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004266 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004267 ALOGD("%s: returning existing instance of adev", __func__);
4268 ALOGD("%s: exit", __func__);
4269 pthread_mutex_unlock(&adev_init_lock);
4270 return 0;
4271 }
4272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 adev = calloc(1, sizeof(struct audio_device));
4274
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004275 if (!adev) {
4276 pthread_mutex_unlock(&adev_init_lock);
4277 return -ENOMEM;
4278 }
4279
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004280 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4283 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4284 adev->device.common.module = (struct hw_module_t *)module;
4285 adev->device.common.close = adev_close;
4286
4287 adev->device.init_check = adev_init_check;
4288 adev->device.set_voice_volume = adev_set_voice_volume;
4289 adev->device.set_master_volume = adev_set_master_volume;
4290 adev->device.get_master_volume = adev_get_master_volume;
4291 adev->device.set_master_mute = adev_set_master_mute;
4292 adev->device.get_master_mute = adev_get_master_mute;
4293 adev->device.set_mode = adev_set_mode;
4294 adev->device.set_mic_mute = adev_set_mic_mute;
4295 adev->device.get_mic_mute = adev_get_mic_mute;
4296 adev->device.set_parameters = adev_set_parameters;
4297 adev->device.get_parameters = adev_get_parameters;
4298 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4299 adev->device.open_output_stream = adev_open_output_stream;
4300 adev->device.close_output_stream = adev_close_output_stream;
4301 adev->device.open_input_stream = adev_open_input_stream;
4302 adev->device.close_input_stream = adev_close_input_stream;
4303 adev->device.dump = adev_dump;
4304
4305 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004307 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004308 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004311 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004312 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004313 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004314 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004315 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004316 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004317 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004318 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304319 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304320 adev->perf_lock_opts[0] = 0x101;
4321 adev->perf_lock_opts[1] = 0x20E;
4322 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304323
4324 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4325 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004327 adev->platform = platform_init(adev);
4328 if (!adev->platform) {
4329 free(adev->snd_dev_ref_cnt);
4330 free(adev);
4331 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4332 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004333 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004334 return -EINVAL;
4335 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004336
Naresh Tanniru4c630392014-05-12 01:05:52 +05304337 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4338
Eric Laurentc4aef752013-09-12 17:45:53 -07004339 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4340 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4341 if (adev->visualizer_lib == NULL) {
4342 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4343 } else {
4344 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4345 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004346 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004347 "visualizer_hal_start_output");
4348 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004349 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004350 "visualizer_hal_stop_output");
4351 }
4352 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004353 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004354 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004355
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004356 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4357 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4358 if (adev->offload_effects_lib == NULL) {
4359 ALOGE("%s: DLOPEN failed for %s", __func__,
4360 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4361 } else {
4362 ALOGV("%s: DLOPEN successful for %s", __func__,
4363 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4364 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304365 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004366 "offload_effects_bundle_hal_start_output");
4367 adev->offload_effects_stop_output =
4368 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4369 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004370 adev->offload_effects_set_hpx_state =
4371 (int (*)(bool))dlsym(adev->offload_effects_lib,
4372 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304373 adev->offload_effects_get_parameters =
4374 (void (*)(struct str_parms *, struct str_parms *))
4375 dlsym(adev->offload_effects_lib,
4376 "offload_effects_bundle_get_parameters");
4377 adev->offload_effects_set_parameters =
4378 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4379 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004380 }
4381 }
4382
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004383 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4384 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4385 if (adev->adm_lib == NULL) {
4386 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4387 } else {
4388 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4389 adev->adm_init = (adm_init_t)
4390 dlsym(adev->adm_lib, "adm_init");
4391 adev->adm_deinit = (adm_deinit_t)
4392 dlsym(adev->adm_lib, "adm_deinit");
4393 adev->adm_register_input_stream = (adm_register_input_stream_t)
4394 dlsym(adev->adm_lib, "adm_register_input_stream");
4395 adev->adm_register_output_stream = (adm_register_output_stream_t)
4396 dlsym(adev->adm_lib, "adm_register_output_stream");
4397 adev->adm_deregister_stream = (adm_deregister_stream_t)
4398 dlsym(adev->adm_lib, "adm_deregister_stream");
4399 adev->adm_request_focus = (adm_request_focus_t)
4400 dlsym(adev->adm_lib, "adm_request_focus");
4401 adev->adm_abandon_focus = (adm_abandon_focus_t)
4402 dlsym(adev->adm_lib, "adm_abandon_focus");
4403 }
4404 }
4405
Mingming Yin514a8bc2014-07-29 15:22:21 -07004406 adev->bt_wb_speech_enabled = false;
4407
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004408 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 *device = &adev->device.common;
4410
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004411 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4412 &adev->streams_output_cfg_list);
4413
Kiran Kandi910e1862013-10-29 13:29:42 -07004414 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004415
4416 char value[PROPERTY_VALUE_MAX];
4417 int trial;
4418 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4419 trial = atoi(value);
4420 if (period_size_is_plausible_for_low_latency(trial)) {
4421 pcm_config_low_latency.period_size = trial;
4422 pcm_config_low_latency.start_threshold = trial / 4;
4423 pcm_config_low_latency.avail_min = trial / 4;
4424 configured_low_latency_capture_period_size = trial;
4425 }
4426 }
4427 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4428 trial = atoi(value);
4429 if (period_size_is_plausible_for_low_latency(trial)) {
4430 configured_low_latency_capture_period_size = trial;
4431 }
4432 }
4433
vivek mehta446c3962015-09-14 10:57:35 -07004434 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004435 pthread_mutex_unlock(&adev_init_lock);
4436
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004437 if (adev->adm_init)
4438 adev->adm_data = adev->adm_init();
4439
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304440 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004441 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004442 return 0;
4443}
4444
4445static struct hw_module_methods_t hal_module_methods = {
4446 .open = adev_open,
4447};
4448
4449struct audio_module HAL_MODULE_INFO_SYM = {
4450 .common = {
4451 .tag = HARDWARE_MODULE_TAG,
4452 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4453 .hal_api_version = HARDWARE_HAL_API_VERSION,
4454 .id = AUDIO_HARDWARE_MODULE_ID,
4455 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004456 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457 .methods = &hal_module_methods,
4458 },
4459};