blob: f18d4cf420da40e33cc3a6e497aa4c880b3269d8 [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
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530508
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700509 if (audio_extn_spkr_prot_is_enabled())
510 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 /* start usb playback thread */
512 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
513 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
514 audio_extn_usb_start_playback(adev);
515
516 /* start usb capture thread */
517 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
518 audio_extn_usb_start_capture(adev);
519
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800520 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
521 audio_extn_spkr_prot_is_enabled()) {
522 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 adev->snd_dev_ref_cnt[snd_device]--;
524 return -EINVAL;
525 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200526 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800527 if (audio_extn_spkr_prot_start_processing(snd_device)) {
528 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200529 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800530 return -EINVAL;
531 }
532 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700533 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700534 /* due to the possibility of calibration overwrite between listen
535 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700540 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 return -EINVAL;
547 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300548 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700549 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530550
551 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
552 !adev->native_playback_enabled &&
553 audio_is_true_native_stream_active(adev)) {
554 ALOGD("%s: %d: napb: enabling native mode in hardware",
555 __func__, __LINE__);
556 audio_route_apply_and_update_path(adev->audio_route,
557 "true-native-mode");
558 adev->native_playback_enabled = true;
559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 return 0;
562}
563
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700564int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700565 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
568
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 if (snd_device < SND_DEVICE_MIN ||
570 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800571 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800572 return -EINVAL;
573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
575 ALOGE("%s: device ref cnt is already 0", __func__);
576 return -EINVAL;
577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700580
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
582 ALOGE("%s: Invalid sound device returned", __func__);
583 return -EINVAL;
584 }
585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700587 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800588 /* exit usb play back thread */
589 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
590 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
591 audio_extn_usb_stop_playback();
592
593 /* exit usb capture thread */
594 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700595 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800596
597 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ashish Jain81eb2a82015-05-13 10:52:34 +0530604 if (snd_device == SND_DEVICE_OUT_HDMI)
605 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530606 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
607 adev->native_playback_enabled) {
608 ALOGD("%s: %d: napb: disabling native mode in hardware",
609 __func__, __LINE__);
610 audio_route_reset_and_update_path(adev->audio_route,
611 "true-native-mode");
612 adev->native_playback_enabled = false;
613 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530614
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200615 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700616 audio_extn_sound_trigger_update_device_status(snd_device,
617 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530618 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800619 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622 return 0;
623}
624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625static void check_usecases_codec_backend(struct audio_device *adev,
626 struct audio_usecase *uc_info,
627 snd_device_t snd_device)
628{
629 struct listnode *node;
630 struct audio_usecase *usecase;
631 bool switch_device[AUDIO_USECASE_MAX];
632 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800633 int backend_idx = DEFAULT_CODEC_BACKEND;
634 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635
636 /*
637 * This function is to make sure that all the usecases that are active on
638 * the hardware codec backend are always routed to any one device that is
639 * handled by the hardware codec.
640 * For example, if low-latency and deep-buffer usecases are currently active
641 * on speaker and out_set_parameters(headset) is received on low-latency
642 * output, then we have to make sure deep-buffer is also switched to headset,
643 * because of the limitation that both the devices cannot be enabled
644 * at the same time as they share the same backend.
645 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700646 /*
647 * This call is to check if we need to force routing for a particular stream
648 * If there is a backend configuration change for the device when a
649 * new stream starts, then ADM needs to be closed and re-opened with the new
650 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700652 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
654 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530655
656 ALOGD("%s:becf: force routing %d", __func__, force_routing);
657
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800660 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800661 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 for (i = 0; i < AUDIO_USECASE_MAX; i++)
663 switch_device[i] = false;
664
665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667
668 if (usecase == uc_info)
669 continue;
670 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
673 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
674 __func__, i, backend_idx, usecase_backend_idx,
675 platform_get_snd_device_name(snd_device),
676 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800677
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800678 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700679 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800680 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
681 usecase_backend_idx == backend_idx) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530682 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
683 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700684 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 switch_device[usecase->id] = true;
687 num_uc_to_switch++;
688 }
689 }
690
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
692 num_uc_to_switch);
693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530697 /* Make sure the previous devices to be disabled first and then enable the
698 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 list_for_each(node, &adev->usecase_list) {
700 usecase = node_to_item(node, struct audio_usecase, list);
701 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
704 }
705
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
708 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700710 }
711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 /* Re-route all the usecases on the shared backend other than the
714 specified usecase to new snd devices */
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530717 /* Update the out_snd_device only before enabling the audio route */
718 if (switch_device[usecase->id]) {
719 usecase->out_snd_device = snd_device;
720 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530721 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530722 use_case_table[usecase->id],
723 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530724 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728 }
729}
730
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731static void check_and_route_capture_usecases(struct audio_device *adev,
732 struct audio_usecase *uc_info,
733 snd_device_t snd_device)
734{
735 struct listnode *node;
736 struct audio_usecase *usecase;
737 bool switch_device[AUDIO_USECASE_MAX];
738 int i, num_uc_to_switch = 0;
739
740 /*
741 * This function is to make sure that all the active capture usecases
742 * are always routed to the same input sound device.
743 * For example, if audio-record and voice-call usecases are currently
744 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
745 * is received for voice call then we have to make sure that audio-record
746 * usecase is also switched to earpiece i.e. voice-dmic-ef,
747 * because of the limitation that two devices cannot be enabled
748 * at the same time if they share the same backend.
749 */
750 for (i = 0; i < AUDIO_USECASE_MAX; i++)
751 switch_device[i] = false;
752
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800755 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700757 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700758 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530759 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
760 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700761 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
763 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700764 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700765 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700766 switch_device[usecase->id] = true;
767 num_uc_to_switch++;
768 }
769 }
770
771 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700772 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700773
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530774 /* Make sure the previous devices to be disabled first and then enable the
775 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 list_for_each(node, &adev->usecase_list) {
777 usecase = node_to_item(node, struct audio_usecase, list);
778 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700779 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800780 }
781 }
782
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
785 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700786 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 }
788 }
789
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700790 /* Re-route all the usecases on the shared backend other than the
791 specified usecase to new snd devices */
792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
794 /* Update the in_snd_device only before enabling the audio route */
795 if (switch_device[usecase->id] ) {
796 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800797 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530798 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 }
800 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700801 }
802}
803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700805static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700807 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700808 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809
810 switch (channels) {
811 /*
812 * Do not handle stereo output in Multi-channel cases
813 * Stereo case is handled in normal playback path
814 */
815 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700816 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
819 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
820 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
821 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800822 break;
823 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700824 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
828 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
829 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
830 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800831 break;
832 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700833 ALOGE("HDMI does not support multi channel playback");
834 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835 break;
836 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700837 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800838}
839
Alexy Josephb1379942016-01-29 15:49:38 -0800840audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800841 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842{
843 struct audio_usecase *usecase;
844 struct listnode *node;
845
846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800848 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700849 ALOGV("%s: usecase id %d", __func__, usecase->id);
850 return usecase->id;
851 }
852 }
853 return USECASE_INVALID;
854}
855
Alexy Josephb1379942016-01-29 15:49:38 -0800856struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700857 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858{
859 struct audio_usecase *usecase;
860 struct listnode *node;
861
862 list_for_each(node, &adev->usecase_list) {
863 usecase = node_to_item(node, struct audio_usecase, list);
864 if (usecase->id == uc_id)
865 return usecase;
866 }
867 return NULL;
868}
869
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530870/*
871 * is a true native playback active
872 */
873bool audio_is_true_native_stream_active(struct audio_device *adev)
874{
875 bool active = false;
876 int i = 0;
877 struct listnode *node;
878
879 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
880 ALOGV("%s:napb: not in true mode or non hdphones device",
881 __func__);
882 active = false;
883 goto exit;
884 }
885
886 list_for_each(node, &adev->usecase_list) {
887 struct audio_usecase *uc;
888 uc = node_to_item(node, struct audio_usecase, list);
889 struct stream_out *curr_out =
890 (struct stream_out*) uc->stream.out;
891
892 if (curr_out && PCM_PLAYBACK == uc->type) {
893 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
894 "(%d) device %s", __func__, i++, use_case_table[uc->id],
895 uc->id, curr_out->sample_rate,
896 curr_out->bit_width,
897 platform_get_snd_device_name(uc->out_snd_device));
898
899 if (is_offload_usecase(uc->id) &&
900 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
901 active = true;
902 ALOGD("%s:napb:native stream detected", __func__);
903 }
904 }
905 }
906exit:
907 return active;
908}
909
910
911static bool force_device_switch(struct audio_usecase *usecase)
912{
913 bool ret = false;
914 bool is_it_true_mode = false;
915
916 if (is_offload_usecase(usecase->id) &&
917 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800918 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
919 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
920 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530921 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
922 if ((is_it_true_mode && !adev->native_playback_enabled) ||
923 (!is_it_true_mode && adev->native_playback_enabled)){
924 ret = true;
925 ALOGD("napb: time to toggle native mode");
926 }
927 }
928
929 return ret;
930}
931
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700932int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800934 snd_device_t out_snd_device = SND_DEVICE_NONE;
935 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700936 struct audio_usecase *usecase = NULL;
937 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800938 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800939 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800940 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800941 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800943
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530944 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
945
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 usecase = get_usecase_from_list(adev, uc_id);
947 if (usecase == NULL) {
948 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
949 return -EINVAL;
950 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800952 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800953 (usecase->type == VOIP_CALL) ||
954 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700955 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800956 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700957 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958 usecase->devices = usecase->stream.out->devices;
959 } else {
960 /*
961 * If the voice call is active, use the sound devices of voice call usecase
962 * so that it would not result any device switch. All the usecases will
963 * be switched to new device when select_devices() is called for voice call
964 * usecase. This is to avoid switching devices for voice call when
965 * check_usecases_codec_backend() is called below.
966 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800967 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700968 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800969 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700970 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
971 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700972 in_snd_device = vc_usecase->in_snd_device;
973 out_snd_device = vc_usecase->out_snd_device;
974 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800975 } else if (voice_extn_compress_voip_is_active(adev)) {
976 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700977 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530978 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700979 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800980 in_snd_device = voip_usecase->in_snd_device;
981 out_snd_device = voip_usecase->out_snd_device;
982 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800983 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800984 hfp_ucid = audio_extn_hfp_get_usecase();
985 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700986 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800987 in_snd_device = hfp_usecase->in_snd_device;
988 out_snd_device = hfp_usecase->out_snd_device;
989 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 }
991 if (usecase->type == PCM_PLAYBACK) {
992 usecase->devices = usecase->stream.out->devices;
993 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700994 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700995 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800996 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700997 if (usecase->stream.out == adev->primary_output &&
998 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800999 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001000 select_devices(adev, adev->active_input->usecase);
1001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 } else if (usecase->type == PCM_CAPTURE) {
1004 usecase->devices = usecase->stream.in->device;
1005 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001006 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001007 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001008 if (adev->active_input &&
1009 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301010 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1011 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1012 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001013 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001014 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001015 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1016 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001017 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001018 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001019 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020 }
1021 }
1022
1023 if (out_snd_device == usecase->out_snd_device &&
1024 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301025
1026 if (!force_device_switch(usecase))
1027 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 }
1029
sangwoobc677242013-08-08 16:53:43 +09001030 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001031 out_snd_device, platform_get_snd_device_name(out_snd_device),
1032 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 /*
1035 * Limitation: While in call, to do a device switch we need to disable
1036 * and enable both RX and TX devices though one of them is same as current
1037 * device.
1038 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001039 if ((usecase->type == VOICE_CALL) &&
1040 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1041 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001042 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001043 }
1044
1045 if (((usecase->type == VOICE_CALL) ||
1046 (usecase->type == VOIP_CALL)) &&
1047 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1048 /* Disable sidetone only if voice/voip call already exists */
1049 if (voice_is_call_state_active(adev) ||
1050 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001051 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001052 }
1053
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 /* Disable current sound devices */
1055 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001056 disable_audio_route(adev, usecase);
1057 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 }
1059
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001061 disable_audio_route(adev, usecase);
1062 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 }
1064
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001065 /* Applicable only on the targets that has external modem.
1066 * New device information should be sent to modem before enabling
1067 * the devices to reduce in-call device switch time.
1068 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001069 if ((usecase->type == VOICE_CALL) &&
1070 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1071 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001072 status = platform_switch_voice_call_enable_device_config(adev->platform,
1073 out_snd_device,
1074 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001075 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001076
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 /* Enable new sound devices */
1078 if (out_snd_device != SND_DEVICE_NONE) {
1079 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1080 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001081 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 }
1083
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001084 if (in_snd_device != SND_DEVICE_NONE) {
1085 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001087 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088
Avinash Vaish71a8b972014-07-24 15:36:33 +05301089 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001090 status = platform_switch_voice_call_device_post(adev->platform,
1091 out_snd_device,
1092 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301093 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001094 /* Enable sidetone only if voice/voip call already exists */
1095 if (voice_is_call_state_active(adev) ||
1096 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001097 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301098 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001099
sangwoo170731f2013-06-08 15:36:36 +09001100 usecase->in_snd_device = in_snd_device;
1101 usecase->out_snd_device = out_snd_device;
1102
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301103 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001104 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301105 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001106 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301107 usecase->stream.out->flags,
1108 usecase->stream.out->format,
1109 usecase->stream.out->sample_rate,
1110 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301111 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301112 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001113 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301114 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001115
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001116 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001117
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001118 /* Applicable only on the targets that has external modem.
1119 * Enable device command should be sent to modem only after
1120 * enabling voice call mixer controls
1121 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001122 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001123 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1124 out_snd_device,
1125 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301126 ALOGD("%s: done",__func__);
1127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128 return status;
1129}
1130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131static int stop_input_stream(struct stream_in *in)
1132{
1133 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001134 struct audio_usecase *uc_info;
1135 struct audio_device *adev = in->dev;
1136
Eric Laurentc8400632013-02-14 19:04:54 -08001137 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001138
Eric Laurent994a6932013-07-17 11:51:42 -07001139 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141 uc_info = get_usecase_from_list(adev, in->usecase);
1142 if (uc_info == NULL) {
1143 ALOGE("%s: Could not find the usecase (%d) in the list",
1144 __func__, in->usecase);
1145 return -EINVAL;
1146 }
1147
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001148 /* Close in-call recording streams */
1149 voice_check_and_stop_incall_rec_usecase(adev, in);
1150
Eric Laurent150dbfe2013-02-27 14:31:02 -08001151 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001152 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153
1154 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001155 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001157 list_remove(&uc_info->list);
1158 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159
Eric Laurent994a6932013-07-17 11:51:42 -07001160 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161 return ret;
1162}
1163
1164int start_input_stream(struct stream_in *in)
1165{
1166 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001167 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 struct audio_usecase *uc_info;
1169 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301170 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171
Mingming Yin2664a5b2015-09-03 10:53:11 -07001172 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1173 if (get_usecase_from_list(adev, usecase) == NULL)
1174 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301175 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1176 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001177
Naresh Tanniru80659832014-06-04 18:17:56 +05301178
1179 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301180 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301181 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301182 goto error_config;
1183 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301184
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001185 /* Check if source matches incall recording usecase criteria */
1186 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1187 if (ret)
1188 goto error_config;
1189 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001190 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1191
1192 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1193 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1194 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1195 goto error_config;
1196 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001197
Eric Laurentb23d5282013-05-14 15:27:20 -07001198 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199 if (in->pcm_device_id < 0) {
1200 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1201 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001202 ret = -EINVAL;
1203 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001205
1206 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001207 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001208
1209 if (!uc_info) {
1210 ret = -ENOMEM;
1211 goto error_config;
1212 }
1213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214 uc_info->id = in->usecase;
1215 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001216 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001217 uc_info->devices = in->device;
1218 uc_info->in_snd_device = SND_DEVICE_NONE;
1219 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001221 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301222 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1223 adev->perf_lock_opts,
1224 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001225 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001226
Eric Laurentc8400632013-02-14 19:04:54 -08001227 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001228 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1229
1230 unsigned int flags = PCM_IN;
1231 unsigned int pcm_open_retry_count = 0;
1232
1233 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1234 flags |= PCM_MMAP | PCM_NOIRQ;
1235 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1236 }
1237
1238 while (1) {
1239 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1240 flags, &in->config);
1241 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1242 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1243 if (in->pcm != NULL) {
1244 pcm_close(in->pcm);
1245 in->pcm = NULL;
1246 }
1247 if (pcm_open_retry_count-- == 0) {
1248 ret = -EIO;
1249 goto error_open;
1250 }
1251 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1252 continue;
1253 }
1254 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001255 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001256
1257 ALOGV("%s: pcm_prepare", __func__);
1258 ret = pcm_prepare(in->pcm);
1259 if (ret < 0) {
1260 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1261 pcm_close(in->pcm);
1262 in->pcm = NULL;
1263 goto error_open;
1264 }
1265
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301266 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001267 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001268
Eric Laurentc8400632013-02-14 19:04:54 -08001269 return ret;
1270
1271error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301272 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001274error_config:
1275 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301276 /*
1277 * sleep 50ms to allow sufficient time for kernel
1278 * drivers to recover incases like SSR.
1279 */
1280 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001282
1283 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284}
1285
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001286void lock_input_stream(struct stream_in *in)
1287{
1288 pthread_mutex_lock(&in->pre_lock);
1289 pthread_mutex_lock(&in->lock);
1290 pthread_mutex_unlock(&in->pre_lock);
1291}
1292
1293void lock_output_stream(struct stream_out *out)
1294{
1295 pthread_mutex_lock(&out->pre_lock);
1296 pthread_mutex_lock(&out->lock);
1297 pthread_mutex_unlock(&out->pre_lock);
1298}
1299
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300/* must be called with out->lock locked */
1301static int send_offload_cmd_l(struct stream_out* out, int command)
1302{
1303 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1304
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001305 if (!cmd) {
1306 ALOGE("failed to allocate mem for command 0x%x", command);
1307 return -ENOMEM;
1308 }
1309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 ALOGVV("%s %d", __func__, command);
1311
1312 cmd->cmd = command;
1313 list_add_tail(&out->offload_cmd_list, &cmd->node);
1314 pthread_cond_signal(&out->offload_cond);
1315 return 0;
1316}
1317
1318/* must be called iwth out->lock locked */
1319static void stop_compressed_output_l(struct stream_out *out)
1320{
1321 out->offload_state = OFFLOAD_STATE_IDLE;
1322 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001323 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001324 if (out->compr != NULL) {
1325 compress_stop(out->compr);
1326 while (out->offload_thread_blocked) {
1327 pthread_cond_wait(&out->cond, &out->lock);
1328 }
1329 }
1330}
1331
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001332bool is_offload_usecase(audio_usecase_t uc_id)
1333{
1334 unsigned int i;
1335 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1336 if (uc_id == offload_usecases[i])
1337 return true;
1338 }
1339 return false;
1340}
1341
vivek mehta446c3962015-09-14 10:57:35 -07001342static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001343{
vivek mehta446c3962015-09-14 10:57:35 -07001344 audio_usecase_t ret_uc = USECASE_INVALID;
1345 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001346 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001347 if (!adev->multi_offload_enable) {
1348 if (is_direct_pcm)
1349 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1350 else
1351 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001352
vivek mehta446c3962015-09-14 10:57:35 -07001353 pthread_mutex_lock(&adev->lock);
1354 if (get_usecase_from_list(adev, ret_uc) != NULL)
1355 ret_uc = USECASE_INVALID;
1356 pthread_mutex_unlock(&adev->lock);
1357
1358 return ret_uc;
1359 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001360
1361 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001362 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1363 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1364 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1365 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001366 break;
1367 }
1368 }
vivek mehta446c3962015-09-14 10:57:35 -07001369
1370 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1371 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001372}
1373
1374static void free_offload_usecase(struct audio_device *adev,
1375 audio_usecase_t uc_id)
1376{
vivek mehta446c3962015-09-14 10:57:35 -07001377 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001378 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001379
1380 if (!adev->multi_offload_enable)
1381 return;
1382
1383 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1384 if (offload_usecases[offload_uc_index] == uc_id) {
1385 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001386 break;
1387 }
1388 }
1389 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1390}
1391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392static void *offload_thread_loop(void *context)
1393{
1394 struct stream_out *out = (struct stream_out *) context;
1395 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001396 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001397
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001398 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1399 set_sched_policy(0, SP_FOREGROUND);
1400 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1401
1402 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001403 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001404 for (;;) {
1405 struct offload_cmd *cmd = NULL;
1406 stream_callback_event_t event;
1407 bool send_callback = false;
1408
1409 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1410 __func__, list_empty(&out->offload_cmd_list),
1411 out->offload_state);
1412 if (list_empty(&out->offload_cmd_list)) {
1413 ALOGV("%s SLEEPING", __func__);
1414 pthread_cond_wait(&out->offload_cond, &out->lock);
1415 ALOGV("%s RUNNING", __func__);
1416 continue;
1417 }
1418
1419 item = list_head(&out->offload_cmd_list);
1420 cmd = node_to_item(item, struct offload_cmd, node);
1421 list_remove(item);
1422
1423 ALOGVV("%s STATE %d CMD %d out->compr %p",
1424 __func__, out->offload_state, cmd->cmd, out->compr);
1425
1426 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1427 free(cmd);
1428 break;
1429 }
1430
1431 if (out->compr == NULL) {
1432 ALOGE("%s: Compress handle is NULL", __func__);
1433 pthread_cond_signal(&out->cond);
1434 continue;
1435 }
1436 out->offload_thread_blocked = true;
1437 pthread_mutex_unlock(&out->lock);
1438 send_callback = false;
1439 switch(cmd->cmd) {
1440 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001441 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001442 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001443 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001444 send_callback = true;
1445 event = STREAM_CBK_EVENT_WRITE_READY;
1446 break;
1447 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001448 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301449 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001450 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301451 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001452 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301453 if (ret < 0)
1454 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301455 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301456 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001457 compress_drain(out->compr);
1458 else
1459 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301460 if (ret != -ENETRESET) {
1461 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301462 pthread_mutex_lock(&out->lock);
1463 out->send_new_metadata = 1;
1464 out->send_next_track_params = true;
1465 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301466 event = STREAM_CBK_EVENT_DRAIN_READY;
1467 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1468 } else
1469 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001470 break;
1471 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001472 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001474 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001475 send_callback = true;
1476 event = STREAM_CBK_EVENT_DRAIN_READY;
1477 break;
1478 default:
1479 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1480 break;
1481 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483 out->offload_thread_blocked = false;
1484 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001485 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001486 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001487 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001488 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001489 free(cmd);
1490 }
1491
1492 pthread_cond_signal(&out->cond);
1493 while (!list_empty(&out->offload_cmd_list)) {
1494 item = list_head(&out->offload_cmd_list);
1495 list_remove(item);
1496 free(node_to_item(item, struct offload_cmd, node));
1497 }
1498 pthread_mutex_unlock(&out->lock);
1499
1500 return NULL;
1501}
1502
1503static int create_offload_callback_thread(struct stream_out *out)
1504{
1505 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1506 list_init(&out->offload_cmd_list);
1507 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1508 offload_thread_loop, out);
1509 return 0;
1510}
1511
1512static int destroy_offload_callback_thread(struct stream_out *out)
1513{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001514 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001515 stop_compressed_output_l(out);
1516 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1517
1518 pthread_mutex_unlock(&out->lock);
1519 pthread_join(out->offload_thread, (void **) NULL);
1520 pthread_cond_destroy(&out->offload_cond);
1521
1522 return 0;
1523}
1524
Eric Laurent07eeafd2013-10-06 12:52:49 -07001525static bool allow_hdmi_channel_config(struct audio_device *adev)
1526{
1527 struct listnode *node;
1528 struct audio_usecase *usecase;
1529 bool ret = true;
1530
1531 list_for_each(node, &adev->usecase_list) {
1532 usecase = node_to_item(node, struct audio_usecase, list);
1533 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1534 /*
1535 * If voice call is already existing, do not proceed further to avoid
1536 * disabling/enabling both RX and TX devices, CSD calls, etc.
1537 * Once the voice call done, the HDMI channels can be configured to
1538 * max channels of remaining use cases.
1539 */
1540 if (usecase->id == USECASE_VOICE_CALL) {
1541 ALOGD("%s: voice call is active, no change in HDMI channels",
1542 __func__);
1543 ret = false;
1544 break;
1545 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1546 ALOGD("%s: multi channel playback is active, "
1547 "no change in HDMI channels", __func__);
1548 ret = false;
1549 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001550 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001551 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001552 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1553 ", no change in HDMI channels", __func__,
1554 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001555 ret = false;
1556 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001557 }
1558 }
1559 }
1560 return ret;
1561}
1562
1563static int check_and_set_hdmi_channels(struct audio_device *adev,
1564 unsigned int channels)
1565{
1566 struct listnode *node;
1567 struct audio_usecase *usecase;
1568
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001569 unsigned int supported_channels = platform_edid_get_max_channels(
1570 adev->platform);
1571 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001572 /* Check if change in HDMI channel config is allowed */
1573 if (!allow_hdmi_channel_config(adev))
1574 return 0;
1575
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001576 if (channels > supported_channels)
1577 channels = supported_channels;
1578
Eric Laurent07eeafd2013-10-06 12:52:49 -07001579 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001580 ALOGD("%s: Requested channels are same as current channels(%d)",
1581 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001582 return 0;
1583 }
1584
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001585 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001586 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001587 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001588 adev->cur_hdmi_channels = channels;
1589
1590 /*
1591 * Deroute all the playback streams routed to HDMI so that
1592 * the back end is deactivated. Note that backend will not
1593 * be deactivated if any one stream is connected to it.
1594 */
1595 list_for_each(node, &adev->usecase_list) {
1596 usecase = node_to_item(node, struct audio_usecase, list);
1597 if (usecase->type == PCM_PLAYBACK &&
1598 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001599 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001600 }
1601 }
1602
1603 /*
1604 * Enable all the streams disabled above. Now the HDMI backend
1605 * will be activated with new channel configuration
1606 */
1607 list_for_each(node, &adev->usecase_list) {
1608 usecase = node_to_item(node, struct audio_usecase, list);
1609 if (usecase->type == PCM_PLAYBACK &&
1610 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001611 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001612 }
1613 }
1614
1615 return 0;
1616}
1617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618static int stop_output_stream(struct stream_out *out)
1619{
1620 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 struct audio_usecase *uc_info;
1622 struct audio_device *adev = out->dev;
1623
Eric Laurent994a6932013-07-17 11:51:42 -07001624 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 uc_info = get_usecase_from_list(adev, out->usecase);
1627 if (uc_info == NULL) {
1628 ALOGE("%s: Could not find the usecase (%d) in the list",
1629 __func__, out->usecase);
1630 return -EINVAL;
1631 }
1632
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001633 if (is_offload_usecase(out->usecase) &&
1634 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001635 if (adev->visualizer_stop_output != NULL)
1636 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001637
1638 audio_extn_dts_remove_state_notifier_node(out->usecase);
1639
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001640 if (adev->offload_effects_stop_output != NULL)
1641 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1642 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001643
Eric Laurent150dbfe2013-02-27 14:31:02 -08001644 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001645 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646
1647 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001648 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001650 list_remove(&uc_info->list);
1651 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001653 if (is_offload_usecase(out->usecase) &&
1654 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1655 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1656 ALOGV("Disable passthrough , reset mixer to pcm");
1657 /* NO_PASSTHROUGH */
1658 out->compr_config.codec->compr_passthr = 0;
1659 audio_extn_dolby_set_hdmi_config(adev, out);
1660 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1661 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001662 /* Must be called after removing the usecase from list */
1663 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1664 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1665
Eric Laurent994a6932013-07-17 11:51:42 -07001666 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 return ret;
1668}
1669
1670int start_output_stream(struct stream_out *out)
1671{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001673 int sink_channels = 0;
1674 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675 struct audio_usecase *uc_info;
1676 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301677 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001679 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1680 ret = -EINVAL;
1681 goto error_config;
1682 }
1683
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301684 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1685 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1686 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301687
Naresh Tanniru80659832014-06-04 18:17:56 +05301688 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301689 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301690 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301691 goto error_config;
1692 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301693
Eric Laurentb23d5282013-05-14 15:27:20 -07001694 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695 if (out->pcm_device_id < 0) {
1696 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1697 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001698 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001699 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 }
1701
1702 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001703
1704 if (!uc_info) {
1705 ret = -ENOMEM;
1706 goto error_config;
1707 }
1708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709 uc_info->id = out->usecase;
1710 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001711 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 uc_info->devices = out->devices;
1713 uc_info->in_snd_device = SND_DEVICE_NONE;
1714 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001715 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001716 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001717 if (is_offload_usecase(out->usecase)) {
1718 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001719 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1720 }
1721 }
Mingming Yin9c041392014-05-01 15:37:31 -07001722 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1723 if (!strncmp("true", prop_value, 4)) {
1724 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001725 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1726 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001727 check_and_set_hdmi_channels(adev, sink_channels);
1728 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001729 if (is_offload_usecase(out->usecase)) {
1730 unsigned int ch_count = out->compr_config.codec->ch_in;
1731 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1732 /* backend channel config for passthrough stream is stereo */
1733 ch_count = 2;
1734 check_and_set_hdmi_channels(adev, ch_count);
1735 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001736 check_and_set_hdmi_channels(adev, out->config.channels);
1737 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001738 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001739 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001740 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301742 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1743 adev->perf_lock_opts,
1744 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745 select_devices(adev, out->usecase);
1746
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001747 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1748 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001749 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001750 unsigned int flags = PCM_OUT;
1751 unsigned int pcm_open_retry_count = 0;
1752 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1753 flags |= PCM_MMAP | PCM_NOIRQ;
1754 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1755 } else
1756 flags |= PCM_MONOTONIC;
1757
1758 while (1) {
1759 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1760 flags, &out->config);
1761 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1762 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1763 if (out->pcm != NULL) {
1764 pcm_close(out->pcm);
1765 out->pcm = NULL;
1766 }
1767 if (pcm_open_retry_count-- == 0) {
1768 ret = -EIO;
1769 goto error_open;
1770 }
1771 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1772 continue;
1773 }
1774 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001776
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001777 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1778 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001779
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001780 ALOGV("%s: pcm_prepare", __func__);
1781 if (pcm_is_ready(out->pcm)) {
1782 ret = pcm_prepare(out->pcm);
1783 if (ret < 0) {
1784 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1785 pcm_close(out->pcm);
1786 out->pcm = NULL;
1787 goto error_open;
1788 }
1789 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001790 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001791 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1792 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001794 out->compr = compress_open(adev->snd_card,
1795 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 COMPRESS_IN, &out->compr_config);
1797 if (out->compr && !is_compress_ready(out->compr)) {
1798 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1799 compress_close(out->compr);
1800 out->compr = NULL;
1801 ret = -EIO;
1802 goto error_open;
1803 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301804 /* compress_open sends params of the track, so reset the flag here */
1805 out->is_compr_metadata_avail = false;
1806
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->offload_callback)
1808 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001809
Fred Oh3f43e742015-03-04 18:42:34 -08001810 /* Since small bufs uses blocking writes, a write will be blocked
1811 for the default max poll time (20s) in the event of an SSR.
1812 Reduce the poll time to observe and deal with SSR faster.
1813 */
1814 if (out->use_small_bufs) {
1815 compress_set_max_poll_wait(out->compr, 1000);
1816 }
1817
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001818 audio_extn_dts_create_state_notifier_node(out->usecase);
1819 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1820 popcount(out->channel_mask),
1821 out->playback_started);
1822
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001823#ifdef DS1_DOLBY_DDP_ENABLED
1824 if (audio_extn_is_dolby_format(out->format))
1825 audio_extn_dolby_send_ddp_endp_params(adev);
1826#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001827 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1828 if (adev->visualizer_start_output != NULL)
1829 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1830 if (adev->offload_effects_start_output != NULL)
1831 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001832 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301835 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001836 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301840 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001842error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301843 /*
1844 * sleep 50ms to allow sufficient time for kernel
1845 * drivers to recover incases like SSR.
1846 */
1847 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001848 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849}
1850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851static int check_input_parameters(uint32_t sample_rate,
1852 audio_format_t format,
1853 int channel_count)
1854{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001855 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001857 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001858 !voice_extn_compress_voip_is_format_supported(format) &&
1859 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001860
1861 switch (channel_count) {
1862 case 1:
1863 case 2:
1864 case 6:
1865 break;
1866 default:
1867 ret = -EINVAL;
1868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869
1870 switch (sample_rate) {
1871 case 8000:
1872 case 11025:
1873 case 12000:
1874 case 16000:
1875 case 22050:
1876 case 24000:
1877 case 32000:
1878 case 44100:
1879 case 48000:
1880 break;
1881 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001882 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883 }
1884
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001885 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886}
1887
1888static size_t get_input_buffer_size(uint32_t sample_rate,
1889 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001890 int channel_count,
1891 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892{
1893 size_t size = 0;
1894
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001895 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1896 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001898 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001899 if (is_low_latency)
1900 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001901 /* ToDo: should use frame_size computed based on the format and
1902 channel_count here. */
1903 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001905 /* make sure the size is multiple of 32 bytes
1906 * At 48 kHz mono 16-bit PCM:
1907 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1908 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1909 */
1910 size += 0x1f;
1911 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001912
1913 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914}
1915
1916static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1917{
1918 struct stream_out *out = (struct stream_out *)stream;
1919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921}
1922
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001923static int out_set_sample_rate(struct audio_stream *stream __unused,
1924 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925{
1926 return -ENOSYS;
1927}
1928
1929static size_t out_get_buffer_size(const struct audio_stream *stream)
1930{
1931 struct stream_out *out = (struct stream_out *)stream;
1932
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001933 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001935 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1936 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001937
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001938 return out->config.period_size *
1939 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940}
1941
1942static uint32_t out_get_channels(const struct audio_stream *stream)
1943{
1944 struct stream_out *out = (struct stream_out *)stream;
1945
1946 return out->channel_mask;
1947}
1948
1949static audio_format_t out_get_format(const struct audio_stream *stream)
1950{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 struct stream_out *out = (struct stream_out *)stream;
1952
1953 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954}
1955
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001956static int out_set_format(struct audio_stream *stream __unused,
1957 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958{
1959 return -ENOSYS;
1960}
1961
1962static int out_standby(struct audio_stream *stream)
1963{
1964 struct stream_out *out = (struct stream_out *)stream;
1965 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301967 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1968 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001969 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1970 /* Ignore standby in case of voip call because the voip output
1971 * stream is closed in adev_close_output_stream()
1972 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301973 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001974 return 0;
1975 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001977 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001979 if (adev->adm_deregister_stream)
1980 adev->adm_deregister_stream(adev->adm_data, out->handle);
1981
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001982 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001984 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985 if (out->pcm) {
1986 pcm_close(out->pcm);
1987 out->pcm = NULL;
1988 }
1989 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001990 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301992 out->send_next_track_params = false;
1993 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001994 out->gapless_mdata.encoder_delay = 0;
1995 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996 if (out->compr != NULL) {
1997 compress_close(out->compr);
1998 out->compr = NULL;
1999 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002002 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 }
2004 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302005 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 return 0;
2007}
2008
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002009static int out_dump(const struct audio_stream *stream __unused,
2010 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011{
2012 return 0;
2013}
2014
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002015static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2016{
2017 int ret = 0;
2018 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002019
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002020 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002021 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002022 return -EINVAL;
2023 }
2024
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302025 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002026
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002027 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2028 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302029 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002030 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002031 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2032 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302033 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002034 }
2035
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002036 ALOGV("%s new encoder delay %u and padding %u", __func__,
2037 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2038
2039 return 0;
2040}
2041
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002042static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2043{
2044 return out == adev->primary_output || out == adev->voice_tx_output;
2045}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2048{
2049 struct stream_out *out = (struct stream_out *)stream;
2050 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002051 struct audio_usecase *usecase;
2052 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053 struct str_parms *parms;
2054 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002055 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002056 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057
sangwoobc677242013-08-08 16:53:43 +09002058 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002059 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302061 if (!parms)
2062 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002063 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2064 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002066 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002067 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302070 * When HDMI cable is unplugged/usb hs is disconnected the
2071 * music playback is paused and the policy manager sends routing=0
2072 * But the audioflingercontinues to write data until standby time
2073 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002074 * Avoid this by routing audio to speaker until standby.
2075 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302076 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2077 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002078 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002079 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2080 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002081 }
2082
2083 /*
2084 * select_devices() call below switches all the usecases on the same
2085 * backend to the new device. Refer to check_usecases_codec_backend() in
2086 * the select_devices(). But how do we undo this?
2087 *
2088 * For example, music playback is active on headset (deep-buffer usecase)
2089 * and if we go to ringtones and select a ringtone, low-latency usecase
2090 * will be started on headset+speaker. As we can't enable headset+speaker
2091 * and headset devices at the same time, select_devices() switches the music
2092 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2093 * So when the ringtone playback is completed, how do we undo the same?
2094 *
2095 * We are relying on the out_set_parameters() call on deep-buffer output,
2096 * once the ringtone playback is ended.
2097 * NOTE: We should not check if the current devices are same as new devices.
2098 * Because select_devices() must be called to switch back the music
2099 * playback to headset.
2100 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002101 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002102 out->devices = val;
2103
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302104 if (!out->standby) {
2105 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2106 adev->perf_lock_opts,
2107 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002108 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302109 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2110 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002111
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002112 if (output_drives_call(adev, out)) {
2113 if(!voice_is_in_call(adev)) {
2114 if (adev->mode == AUDIO_MODE_IN_CALL) {
2115 adev->current_call_output = out;
2116 ret = voice_start_call(adev);
2117 }
2118 } else {
2119 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002120 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002121 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002122 }
2123 }
2124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002126 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002128
2129 if (out == adev->primary_output) {
2130 pthread_mutex_lock(&adev->lock);
2131 audio_extn_set_parameters(adev, parms);
2132 pthread_mutex_unlock(&adev->lock);
2133 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002134 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002135 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002136 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002137
2138 audio_extn_dts_create_state_notifier_node(out->usecase);
2139 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2140 popcount(out->channel_mask),
2141 out->playback_started);
2142
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002143 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002144 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302147error:
Eric Laurent994a6932013-07-17 11:51:42 -07002148 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 return ret;
2150}
2151
2152static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2153{
2154 struct stream_out *out = (struct stream_out *)stream;
2155 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002156 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 char value[256];
2158 struct str_parms *reply = str_parms_create();
2159 size_t i, j;
2160 int ret;
2161 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002162
2163 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002164 if (reply) {
2165 str_parms_destroy(reply);
2166 }
2167 if (query) {
2168 str_parms_destroy(query);
2169 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002170 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2171 return NULL;
2172 }
2173
Eric Laurent994a6932013-07-17 11:51:42 -07002174 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2176 if (ret >= 0) {
2177 value[0] = '\0';
2178 i = 0;
2179 while (out->supported_channel_masks[i] != 0) {
2180 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2181 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2182 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002183 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002185 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 first = false;
2187 break;
2188 }
2189 }
2190 i++;
2191 }
2192 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2193 str = str_parms_to_str(reply);
2194 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002195 voice_extn_out_get_parameters(out, query, reply);
2196 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002197 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002198 free(str);
2199 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002200 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002202
Alexy Joseph62142aa2015-11-16 15:10:34 -08002203
2204 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2205 if (ret >= 0) {
2206 value[0] = '\0';
2207 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2208 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302209 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002210 } else {
2211 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302212 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002213 }
2214 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002215 if (str)
2216 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002217 str = str_parms_to_str(reply);
2218 }
2219
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002220 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2221 if (ret >= 0) {
2222 value[0] = '\0';
2223 i = 0;
2224 first = true;
2225 while (out->supported_formats[i] != 0) {
2226 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2227 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2228 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002229 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002230 }
2231 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2232 first = false;
2233 break;
2234 }
2235 }
2236 i++;
2237 }
2238 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002239 if (str)
2240 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002241 str = str_parms_to_str(reply);
2242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 str_parms_destroy(query);
2244 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002245 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 return str;
2247}
2248
2249static uint32_t out_get_latency(const struct audio_stream_out *stream)
2250{
2251 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002252 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253
Alexy Josephaa54c872014-12-03 02:46:47 -08002254 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002255 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002256 } else {
2257 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002259 }
2260
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302261 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002262 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263}
2264
2265static int out_set_volume(struct audio_stream_out *stream, float left,
2266 float right)
2267{
Eric Laurenta9024de2013-04-04 09:19:12 -07002268 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002269 int volume[2];
2270
Eric Laurenta9024de2013-04-04 09:19:12 -07002271 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2272 /* only take left channel into account: the API is for stereo anyway */
2273 out->muted = (left == 0.0f);
2274 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002275 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002276 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2277 /*
2278 * Set mute or umute on HDMI passthrough stream.
2279 * Only take left channel into account.
2280 * Mute is 0 and unmute 1
2281 */
2282 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2283 } else {
2284 char mixer_ctl_name[128];
2285 struct audio_device *adev = out->dev;
2286 struct mixer_ctl *ctl;
2287 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002288 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002290 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2291 "Compress Playback %d Volume", pcm_device_id);
2292 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2293 if (!ctl) {
2294 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2295 __func__, mixer_ctl_name);
2296 return -EINVAL;
2297 }
2298 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2299 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2300 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2301 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002303 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 return -ENOSYS;
2306}
2307
2308static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2309 size_t bytes)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302313 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002314 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002316 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302317
Naresh Tanniru80659832014-06-04 18:17:56 +05302318 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002319
Ashish Jainbbce4322016-02-16 13:25:27 +05302320 if (is_offload_usecase(out->usecase)) {
2321 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302322 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2323 pthread_mutex_unlock(&out->lock);
2324 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302325 } else {
2326 /* increase written size during SSR to avoid mismatch
2327 * with the written frames count in AF
2328 */
2329 out->written += bytes / (out->config.channels * sizeof(short));
2330 ALOGD(" %s: sound card is not active/SSR state", __func__);
2331 ret= -EIO;
2332 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302333 }
2334 }
2335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002337 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002338 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002339 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2340 ret = voice_extn_compress_voip_start_output_stream(out);
2341 else
2342 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002343 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002346 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 goto exit;
2348 }
vivek mehta446c3962015-09-14 10:57:35 -07002349 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002350 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352
Ashish Jain81eb2a82015-05-13 10:52:34 +05302353 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002354 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302355 adev->is_channel_status_set = true;
2356 }
2357
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002358 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002359 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002360 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002361 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002362 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2363 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302364 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2365 ALOGD("copl(%p):send next track params in gapless", out);
2366 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2367 out->send_next_track_params = false;
2368 out->is_compr_metadata_avail = false;
2369 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370 }
2371
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302373 if (ret < 0)
2374 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002375 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002376 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302377 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002378 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302379 } else if (-ENETRESET == ret) {
2380 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2381 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2382 pthread_mutex_unlock(&out->lock);
2383 out_standby(&out->stream.common);
2384 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302386 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002388 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 out->playback_started = 1;
2390 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002391
2392 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2393 popcount(out->channel_mask),
2394 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 }
2396 pthread_mutex_unlock(&out->lock);
2397 return ret;
2398 } else {
2399 if (out->pcm) {
2400 if (out->muted)
2401 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002402
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002404
2405 if (adev->adm_request_focus)
2406 adev->adm_request_focus(adev->adm_data, out->handle);
2407
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002408 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2409 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2410 else
2411 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002412
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302413 if (ret < 0)
2414 ret = -errno;
2415 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002416 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002417
2418 if (adev->adm_abandon_focus)
2419 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 }
2422
2423exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302424 /* ToDo: There may be a corner case when SSR happens back to back during
2425 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302426 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302427 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302428 }
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 pthread_mutex_unlock(&out->lock);
2431
2432 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002433 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002434 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302435 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302436 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302437 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302438 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302439 out->standby = true;
2440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302442 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302443 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444 }
2445 return bytes;
2446}
2447
2448static int out_get_render_position(const struct audio_stream_out *stream,
2449 uint32_t *dsp_frames)
2450{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302452 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002453
2454 if (dsp_frames == NULL)
2455 return -EINVAL;
2456
2457 *dsp_frames = 0;
2458 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002459 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302462 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302464 if (ret < 0)
2465 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 ALOGVV("%s rendered frames %d sample_rate %d",
2467 __func__, *dsp_frames, out->sample_rate);
2468 }
2469 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302470 if (-ENETRESET == ret) {
2471 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2472 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2473 return -EINVAL;
2474 } else if(ret < 0) {
2475 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2476 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302477 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2478 /*
2479 * Handle corner case where compress session is closed during SSR
2480 * and timestamp is queried
2481 */
2482 ALOGE(" ERROR: sound card not active, return error");
2483 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302484 } else {
2485 return 0;
2486 }
Zhou Song32a556e2015-05-05 10:46:56 +08002487 } else if (audio_is_linear_pcm(out->format)) {
2488 *dsp_frames = out->written;
2489 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 } else
2491 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492}
2493
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002494static int out_add_audio_effect(const struct audio_stream *stream __unused,
2495 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496{
2497 return 0;
2498}
2499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002500static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2501 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
2503 return 0;
2504}
2505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002506static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2507 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508{
2509 return -EINVAL;
2510}
2511
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002512static int out_get_presentation_position(const struct audio_stream_out *stream,
2513 uint64_t *frames, struct timespec *timestamp)
2514{
2515 struct stream_out *out = (struct stream_out *)stream;
2516 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002517 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002518
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002519 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002520
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002521 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002522 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302523 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002524 &out->sample_rate);
2525 ALOGVV("%s rendered frames %ld sample_rate %d",
2526 __func__, dsp_frames, out->sample_rate);
2527 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302528 if (ret < 0)
2529 ret = -errno;
2530 if (-ENETRESET == ret) {
2531 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2532 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2533 ret = -EINVAL;
2534 } else
2535 ret = 0;
2536
Eric Laurent949a0892013-09-20 09:20:13 -07002537 /* this is the best we can do */
2538 clock_gettime(CLOCK_MONOTONIC, timestamp);
2539 }
2540 } else {
2541 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002542 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002543 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2544 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002545 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002546 // This adjustment accounts for buffering after app processor.
2547 // It is based on estimated DSP latency per use case, rather than exact.
2548 signed_frames -=
2549 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2550
Eric Laurent949a0892013-09-20 09:20:13 -07002551 // It would be unusual for this value to be negative, but check just in case ...
2552 if (signed_frames >= 0) {
2553 *frames = signed_frames;
2554 ret = 0;
2555 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002556 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302557 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2558 *frames = out->written;
2559 clock_gettime(CLOCK_MONOTONIC, timestamp);
2560 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002561 }
2562 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002563 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002564 return ret;
2565}
2566
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567static int out_set_callback(struct audio_stream_out *stream,
2568 stream_callback_t callback, void *cookie)
2569{
2570 struct stream_out *out = (struct stream_out *)stream;
2571
2572 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002573 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 out->offload_callback = callback;
2575 out->offload_cookie = cookie;
2576 pthread_mutex_unlock(&out->lock);
2577 return 0;
2578}
2579
2580static int out_pause(struct audio_stream_out* stream)
2581{
2582 struct stream_out *out = (struct stream_out *)stream;
2583 int status = -ENOSYS;
2584 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002585 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002586 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002587 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302589 struct audio_device *adev = out->dev;
2590 int snd_scard_state = get_snd_card_state(adev);
2591
2592 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2593 status = compress_pause(out->compr);
2594
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002596
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302597 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002598 audio_extn_dts_notify_playback_state(out->usecase, 0,
2599 out->sample_rate, popcount(out->channel_mask),
2600 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002601 }
2602 pthread_mutex_unlock(&out->lock);
2603 }
2604 return status;
2605}
2606
2607static int out_resume(struct audio_stream_out* stream)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610 int status = -ENOSYS;
2611 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002612 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002613 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002615 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302617 struct audio_device *adev = out->dev;
2618 int snd_scard_state = get_snd_card_state(adev);
2619
2620 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2621 status = compress_resume(out->compr);
2622
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002624
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302625 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002626 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2627 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002628 }
2629 pthread_mutex_unlock(&out->lock);
2630 }
2631 return status;
2632}
2633
2634static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2635{
2636 struct stream_out *out = (struct stream_out *)stream;
2637 int status = -ENOSYS;
2638 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002639 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002640 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002641 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2642 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2643 else
2644 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2645 pthread_mutex_unlock(&out->lock);
2646 }
2647 return status;
2648}
2649
2650static int out_flush(struct audio_stream_out* stream)
2651{
2652 struct stream_out *out = (struct stream_out *)stream;
2653 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002654 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002655 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002656 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657 stop_compressed_output_l(out);
2658 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002659 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 return 0;
2661 }
2662 return -ENOSYS;
2663}
2664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665/** audio_stream_in implementation **/
2666static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2667{
2668 struct stream_in *in = (struct stream_in *)stream;
2669
2670 return in->config.rate;
2671}
2672
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002673static int in_set_sample_rate(struct audio_stream *stream __unused,
2674 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
2676 return -ENOSYS;
2677}
2678
2679static size_t in_get_buffer_size(const struct audio_stream *stream)
2680{
2681 struct stream_in *in = (struct stream_in *)stream;
2682
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002683 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2684 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002685 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2686 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002687
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002688 return in->config.period_size *
2689 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690}
2691
2692static uint32_t in_get_channels(const struct audio_stream *stream)
2693{
2694 struct stream_in *in = (struct stream_in *)stream;
2695
2696 return in->channel_mask;
2697}
2698
2699static audio_format_t in_get_format(const struct audio_stream *stream)
2700{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002701 struct stream_in *in = (struct stream_in *)stream;
2702
2703 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002706static int in_set_format(struct audio_stream *stream __unused,
2707 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
2709 return -ENOSYS;
2710}
2711
2712static int in_standby(struct audio_stream *stream)
2713{
2714 struct stream_in *in = (struct stream_in *)stream;
2715 struct audio_device *adev = in->dev;
2716 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302717 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2718 stream, in->usecase, use_case_table[in->usecase]);
2719
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002720 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2721 /* Ignore standby in case of voip call because the voip input
2722 * stream is closed in adev_close_input_stream()
2723 */
2724 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2725 return status;
2726 }
2727
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002728 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002729 if (!in->standby && in->is_st_session) {
2730 ALOGD("%s: sound trigger pcm stop lab", __func__);
2731 audio_extn_sound_trigger_stop_lab(in);
2732 in->standby = 1;
2733 }
2734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002736 if (adev->adm_deregister_stream)
2737 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2738
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002739 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002741 if (in->pcm) {
2742 pcm_close(in->pcm);
2743 in->pcm = NULL;
2744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002746 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 }
2748 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 return status;
2751}
2752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002753static int in_dump(const struct audio_stream *stream __unused,
2754 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 return 0;
2757}
2758
2759static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2760{
2761 struct stream_in *in = (struct stream_in *)stream;
2762 struct audio_device *adev = in->dev;
2763 struct str_parms *parms;
2764 char *str;
2765 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002766 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302768 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 parms = str_parms_create_str(kvpairs);
2770
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302771 if (!parms)
2772 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002773 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002774 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002775
2776 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2777 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 val = atoi(value);
2779 /* no audio source uses val == 0 */
2780 if ((in->source != val) && (val != 0)) {
2781 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002782 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2783 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2784 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2785 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002786 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002787 err = voice_extn_compress_voip_open_input_stream(in);
2788 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002789 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002790 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002791 }
2792 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 }
2794 }
2795
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002796 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2797 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002799 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 in->device = val;
2801 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002802 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002803 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 }
2805 }
2806
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002807done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002809 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810
2811 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302812error:
Eric Laurent994a6932013-07-17 11:51:42 -07002813 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 return ret;
2815}
2816
2817static char* in_get_parameters(const struct audio_stream *stream,
2818 const char *keys)
2819{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002820 struct stream_in *in = (struct stream_in *)stream;
2821 struct str_parms *query = str_parms_create_str(keys);
2822 char *str;
2823 char value[256];
2824 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002825
2826 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002827 if (reply) {
2828 str_parms_destroy(reply);
2829 }
2830 if (query) {
2831 str_parms_destroy(query);
2832 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002833 ALOGE("in_get_parameters: failed to create query or reply");
2834 return NULL;
2835 }
2836
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002837 ALOGV("%s: enter: keys - %s", __func__, keys);
2838
2839 voice_extn_in_get_parameters(in, query, reply);
2840
2841 str = str_parms_to_str(reply);
2842 str_parms_destroy(query);
2843 str_parms_destroy(reply);
2844
2845 ALOGV("%s: exit: returns - %s", __func__, str);
2846 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847}
2848
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002849static int in_set_gain(struct audio_stream_in *stream __unused,
2850 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851{
2852 return 0;
2853}
2854
2855static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2856 size_t bytes)
2857{
2858 struct stream_in *in = (struct stream_in *)stream;
2859 struct audio_device *adev = in->dev;
2860 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302861 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002863 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302864
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002865 if (in->is_st_session) {
2866 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2867 /* Read from sound trigger HAL */
2868 audio_extn_sound_trigger_read(in, buffer, bytes);
2869 pthread_mutex_unlock(&in->lock);
2870 return bytes;
2871 }
2872
Ashish Jainbbce4322016-02-16 13:25:27 +05302873 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002874 ALOGD(" %s: sound card is not active/SSR state", __func__);
2875 ret= -EIO;;
2876 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302877 }
2878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002880 pthread_mutex_lock(&adev->lock);
2881 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2882 ret = voice_extn_compress_voip_start_input_stream(in);
2883 else
2884 ret = start_input_stream(in);
2885 pthread_mutex_unlock(&adev->lock);
2886 if (ret != 0) {
2887 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 }
2889 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002890 if (adev->adm_register_input_stream)
2891 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002894 if (adev->adm_request_focus)
2895 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002898 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002899 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002900 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2901 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002902 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2903 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002904 else
2905 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302906 if (ret < 0)
2907 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 }
2909
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002910 if (adev->adm_abandon_focus)
2911 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 /*
2914 * Instead of writing zeroes here, we could trust the hardware
2915 * to always provide zeroes when muted.
2916 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302917 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2918 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919 memset(buffer, 0, bytes);
2920
2921exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302922 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302923 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002924 if (-ENETRESET == ret)
2925 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 pthread_mutex_unlock(&in->lock);
2928
2929 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302930 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302931 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302932 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302933 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302934 in->standby = true;
2935 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302936 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002938 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05302939 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302940 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 }
2942 return bytes;
2943}
2944
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002945static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946{
2947 return 0;
2948}
2949
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002950static int add_remove_audio_effect(const struct audio_stream *stream,
2951 effect_handle_t effect,
2952 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002954 struct stream_in *in = (struct stream_in *)stream;
2955 int status = 0;
2956 effect_descriptor_t desc;
2957
2958 status = (*effect)->get_descriptor(effect, &desc);
2959 if (status != 0)
2960 return status;
2961
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002962 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002963 pthread_mutex_lock(&in->dev->lock);
2964 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2965 in->enable_aec != enable &&
2966 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2967 in->enable_aec = enable;
2968 if (!in->standby)
2969 select_devices(in->dev, in->usecase);
2970 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002971 if (in->enable_ns != enable &&
2972 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2973 in->enable_ns = enable;
2974 if (!in->standby)
2975 select_devices(in->dev, in->usecase);
2976 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002977 pthread_mutex_unlock(&in->dev->lock);
2978 pthread_mutex_unlock(&in->lock);
2979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 return 0;
2981}
2982
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002983static int in_add_audio_effect(const struct audio_stream *stream,
2984 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985{
Eric Laurent994a6932013-07-17 11:51:42 -07002986 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002987 return add_remove_audio_effect(stream, effect, true);
2988}
2989
2990static int in_remove_audio_effect(const struct audio_stream *stream,
2991 effect_handle_t effect)
2992{
Eric Laurent994a6932013-07-17 11:51:42 -07002993 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002994 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995}
2996
2997static int adev_open_output_stream(struct audio_hw_device *dev,
2998 audio_io_handle_t handle,
2999 audio_devices_t devices,
3000 audio_output_flags_t flags,
3001 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003002 struct audio_stream_out **stream_out,
3003 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004{
3005 struct audio_device *adev = (struct audio_device *)dev;
3006 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003007 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003008 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303011
3012 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3013 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003014 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303015 return -EINVAL;
3016 }
3017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3019
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303020 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3021 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3022 devices, flags, &out->stream);
3023
3024
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003025 if (!out) {
3026 return -ENOMEM;
3027 }
3028
Haynes Mathew George204045b2015-02-25 20:32:03 -08003029 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003030 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003031 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 if (devices == AUDIO_DEVICE_NONE)
3034 devices = AUDIO_DEVICE_OUT_SPEAKER;
3035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 out->flags = flags;
3037 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003038 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003039 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 out->sample_rate = config->sample_rate;
3041 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3042 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003043 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003044 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003045 out->non_blocking = 0;
3046 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
3048 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003049 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303050 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3051 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003052 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3053 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3054
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003055 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003056 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3057 ret = read_hdmi_channel_masks(out);
3058
3059 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3060 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003061 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003062 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003063 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003064
3065 if (config->sample_rate == 0)
3066 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3067 if (config->channel_mask == 0)
3068 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3069
3070 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3073 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003075 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003077 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3078 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003079 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003080 ret = voice_extn_compress_voip_open_output_stream(out);
3081 if (ret != 0) {
3082 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3083 __func__, ret);
3084 goto error_open;
3085 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003086 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3087 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3090 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3091 ALOGE("%s: Unsupported Offload information", __func__);
3092 ret = -EINVAL;
3093 goto error_open;
3094 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003095
3096 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3097 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3098 ALOGV("read and update_pass through formats");
3099 ret = audio_extn_dolby_update_passt_formats(adev, out);
3100 if(ret != 0) {
3101 goto error_open;
3102 }
3103 if(config->offload_info.format == 0)
3104 config->offload_info.format = out->supported_formats[0];
3105 }
3106
Mingming Yin90310102013-11-13 16:57:00 -08003107 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003108 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003109 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003110 ret = -EINVAL;
3111 goto error_open;
3112 }
3113
3114 out->compr_config.codec = (struct snd_codec *)
3115 calloc(1, sizeof(struct snd_codec));
3116
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003117 if (!out->compr_config.codec) {
3118 ret = -ENOMEM;
3119 goto error_open;
3120 }
3121
vivek mehta0ea887a2015-08-26 14:01:20 -07003122 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003123 out->usecase = get_offload_usecase(adev, true);
3124 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003125 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003126 out->stream.set_callback = out_set_callback;
3127 out->stream.pause = out_pause;
3128 out->stream.resume = out_resume;
3129 out->stream.drain = out_drain;
3130 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003131 out->usecase = get_offload_usecase(adev, false);
3132 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003133 }
vivek mehta446c3962015-09-14 10:57:35 -07003134
3135 if (out->usecase == USECASE_INVALID) {
Alexy Josephb1379942016-01-29 15:49:38 -08003136 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
vivek mehta446c3962015-09-14 10:57:35 -07003137 ret = -EEXIST;
3138 goto error_open;
3139 }
3140
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003141 if (config->offload_info.channel_mask)
3142 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003143 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003145 config->offload_info.channel_mask = config->channel_mask;
3146 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003147 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 out->sample_rate = config->offload_info.sample_rate;
3149
Mingming Yin3ee55c62014-08-04 14:23:35 -07003150 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003152 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003153 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003154 audio_extn_dolby_get_snd_codec_id(adev, out,
3155 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003156 else
3157 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003159
3160 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3161 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003162 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003163 platform_get_pcm_offload_buffer_size(&config->offload_info);
3164 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3165 out->compr_config.fragment_size =
3166 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003167 } else {
3168 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003169 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003170 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3172 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003173 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003174 out->compr_config.codec->bit_rate =
3175 config->offload_info.bit_rate;
3176 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003177 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003178 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303179 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003180 /*TODO: Do we need to change it for passthrough */
3181 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182
Manish Dewangana6fc5442015-08-24 20:30:31 +05303183 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3184 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3185 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3186 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003187 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3188 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003189 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003190 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003191 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3192 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003193
Mingming Yin3ee55c62014-08-04 14:23:35 -07003194 if (out->bit_width == 24) {
3195 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3196 }
3197
Amit Shekhar6f461b12014-08-01 14:52:58 -07003198 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303199 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003200
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3202 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003203
Mingming Yin497419f2015-07-01 16:57:32 -07003204 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003205 //this flag is set from framework only if its for PCM formats
3206 //no need to check for PCM format again
3207 out->non_blocking = 0;
3208 out->use_small_bufs = true;
3209 ALOGI("Keep write blocking for small buff: non_blockling %d",
3210 out->non_blocking);
3211 }
3212
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003213 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303214 out->send_next_track_params = false;
3215 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003216 out->offload_state = OFFLOAD_STATE_IDLE;
3217 out->playback_started = 0;
3218
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003219 audio_extn_dts_create_state_notifier_node(out->usecase);
3220
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003221 create_offload_callback_thread(out);
3222 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3223 __func__, config->offload_info.version,
3224 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003225 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003226 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003227 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3228 ret = voice_check_and_set_incall_music_usecase(adev, out);
3229 if (ret != 0) {
3230 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3231 __func__, ret);
3232 goto error_open;
3233 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003234 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3235 if (config->sample_rate == 0)
3236 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3237 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3238 config->sample_rate != 8000) {
3239 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3240 ret = -EINVAL;
3241 goto error_open;
3242 }
3243 out->sample_rate = config->sample_rate;
3244 out->config.rate = config->sample_rate;
3245 if (config->format == AUDIO_FORMAT_DEFAULT)
3246 config->format = AUDIO_FORMAT_PCM_16_BIT;
3247 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3248 config->format = AUDIO_FORMAT_PCM_16_BIT;
3249 ret = -EINVAL;
3250 goto error_open;
3251 }
3252 out->format = config->format;
3253 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3254 out->config = pcm_config_afe_proxy_playback;
3255 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003256 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3257 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3258 out->config = pcm_config_low_latency;
3259 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003260 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003261 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3263 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003265 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3266 format = AUDIO_FORMAT_PCM_16_BIT;
3267 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3268 out->config = pcm_config_deep_buffer;
3269 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003270 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003271 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003272 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003273 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003274 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003275 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 }
3277
Amit Shekhar1d896042014-10-03 13:16:09 -07003278 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3279 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003280 /* TODO remove this hardcoding and check why width is zero*/
3281 if (out->bit_width == 0)
3282 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003283 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3284 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003285 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303286 out->bit_width, out->channel_mask,
3287 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003288 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3289 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3290 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003291 if(adev->primary_output == NULL)
3292 adev->primary_output = out;
3293 else {
3294 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003295 ret = -EEXIST;
3296 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003297 }
3298 }
3299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 /* Check if this usecase is already existing */
3301 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003302 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3303 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003306 ret = -EEXIST;
3307 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 }
3309 pthread_mutex_unlock(&adev->lock);
3310
3311 out->stream.common.get_sample_rate = out_get_sample_rate;
3312 out->stream.common.set_sample_rate = out_set_sample_rate;
3313 out->stream.common.get_buffer_size = out_get_buffer_size;
3314 out->stream.common.get_channels = out_get_channels;
3315 out->stream.common.get_format = out_get_format;
3316 out->stream.common.set_format = out_set_format;
3317 out->stream.common.standby = out_standby;
3318 out->stream.common.dump = out_dump;
3319 out->stream.common.set_parameters = out_set_parameters;
3320 out->stream.common.get_parameters = out_get_parameters;
3321 out->stream.common.add_audio_effect = out_add_audio_effect;
3322 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3323 out->stream.get_latency = out_get_latency;
3324 out->stream.set_volume = out_set_volume;
3325 out->stream.write = out_write;
3326 out->stream.get_render_position = out_get_render_position;
3327 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003328 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003331 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003332 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333
3334 config->format = out->stream.common.get_format(&out->stream.common);
3335 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3336 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3337
3338 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303339 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003340 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003341
3342 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3343 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3344 popcount(out->channel_mask), out->playback_started);
3345
Eric Laurent994a6932013-07-17 11:51:42 -07003346 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003348
3349error_open:
3350 free(out);
3351 *stream_out = NULL;
3352 ALOGD("%s: exit: ret %d", __func__, ret);
3353 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354}
3355
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003356static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 struct audio_stream_out *stream)
3358{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003359 struct stream_out *out = (struct stream_out *)stream;
3360 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003361 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303363 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3364
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003365 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303366 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003367 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303368 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003369 if(ret != 0)
3370 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3371 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003372 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003373 out_standby(&stream->common);
3374
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003375 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003376 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003377 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003378 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 if (out->compr_config.codec != NULL)
3380 free(out->compr_config.codec);
3381 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003382
3383 if (adev->voice_tx_output == out)
3384 adev->voice_tx_output = NULL;
3385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 pthread_cond_destroy(&out->cond);
3387 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003389 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390}
3391
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003392static void close_compress_sessions(struct audio_device *adev)
3393{
Mingming Yin7b762e72015-03-04 13:47:32 -08003394 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303395 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003396 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003397 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303398
3399 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003400 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303401 if (is_offload_usecase(usecase->id)) {
3402 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003403 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3404 out = usecase->stream.out;
3405 pthread_mutex_unlock(&adev->lock);
3406 out_standby(&out->stream.common);
3407 pthread_mutex_lock(&adev->lock);
3408 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303409 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003410 }
3411 pthread_mutex_unlock(&adev->lock);
3412}
3413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3415{
3416 struct audio_device *adev = (struct audio_device *)dev;
3417 struct str_parms *parms;
3418 char *str;
3419 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003420 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003421 int ret;
3422 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003424 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303427 if (!parms)
3428 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003429 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3430 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303431 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303432 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303433 struct listnode *node;
3434 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303435 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303436 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003437 //close compress sessions on OFFLINE status
3438 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303439 } else if (strstr(snd_card_status, "ONLINE")) {
3440 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303441 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003442 //send dts hpx license if enabled
3443 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303444 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303445 }
3446
3447 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003448 status = voice_set_parameters(adev, parms);
3449 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003450 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003452 status = platform_set_parameters(adev->platform, parms);
3453 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003454 goto done;
3455
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003456 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3457 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003458 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3460 adev->bluetooth_nrec = true;
3461 else
3462 adev->bluetooth_nrec = false;
3463 }
3464
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003465 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3466 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3468 adev->screen_off = false;
3469 else
3470 adev->screen_off = true;
3471 }
3472
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003473 ret = str_parms_get_int(parms, "rotation", &val);
3474 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003475 bool reverse_speakers = false;
3476 switch(val) {
3477 // FIXME: note that the code below assumes that the speakers are in the correct placement
3478 // relative to the user when the device is rotated 90deg from its default rotation. This
3479 // assumption is device-specific, not platform-specific like this code.
3480 case 270:
3481 reverse_speakers = true;
3482 break;
3483 case 0:
3484 case 90:
3485 case 180:
3486 break;
3487 default:
3488 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003489 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003490 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003491 if (status == 0) {
3492 if (adev->speaker_lr_swap != reverse_speakers) {
3493 adev->speaker_lr_swap = reverse_speakers;
3494 // only update the selected device if there is active pcm playback
3495 struct audio_usecase *usecase;
3496 struct listnode *node;
3497 list_for_each(node, &adev->usecase_list) {
3498 usecase = node_to_item(node, struct audio_usecase, list);
3499 if (usecase->type == PCM_PLAYBACK) {
3500 select_devices(adev, usecase->id);
3501 break;
3502 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003503 }
3504 }
3505 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003506 }
3507
Mingming Yin514a8bc2014-07-29 15:22:21 -07003508 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3509 if (ret >= 0) {
3510 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3511 adev->bt_wb_speech_enabled = true;
3512 else
3513 adev->bt_wb_speech_enabled = false;
3514 }
3515
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003516 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3517 if (ret >= 0) {
3518 val = atoi(value);
3519 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3520 ALOGV("cache new edid");
3521 platform_cache_edid(adev->platform);
3522 }
3523 }
3524
3525 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3526 if (ret >= 0) {
3527 val = atoi(value);
3528 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3529 ALOGV("invalidate cached edid");
3530 platform_invalidate_edid(adev->platform);
3531 }
3532 }
3533
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003534 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003535
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003536done:
3537 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003538 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303539error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003540 ALOGV("%s: exit with code(%d)", __func__, status);
3541 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542}
3543
3544static char* adev_get_parameters(const struct audio_hw_device *dev,
3545 const char *keys)
3546{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003547 struct audio_device *adev = (struct audio_device *)dev;
3548 struct str_parms *reply = str_parms_create();
3549 struct str_parms *query = str_parms_create_str(keys);
3550 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303551 char value[256] = {0};
3552 int ret = 0;
3553
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003554 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003555 if (reply) {
3556 str_parms_destroy(reply);
3557 }
3558 if (query) {
3559 str_parms_destroy(query);
3560 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003561 ALOGE("adev_get_parameters: failed to create query or reply");
3562 return NULL;
3563 }
3564
Naresh Tannirud7205b62014-06-20 02:54:48 +05303565 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3566 sizeof(value));
3567 if (ret >=0) {
3568 int val = 1;
3569 pthread_mutex_lock(&adev->snd_card_status.lock);
3570 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3571 val = 0;
3572 pthread_mutex_unlock(&adev->snd_card_status.lock);
3573 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3574 goto exit;
3575 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003576
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003577 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003578 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003579 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003580 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303581 pthread_mutex_unlock(&adev->lock);
3582
Naresh Tannirud7205b62014-06-20 02:54:48 +05303583exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003584 str = str_parms_to_str(reply);
3585 str_parms_destroy(query);
3586 str_parms_destroy(reply);
3587
3588 ALOGV("%s: exit: returns - %s", __func__, str);
3589 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590}
3591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003592static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593{
3594 return 0;
3595}
3596
3597static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3598{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003599 int ret;
3600 struct audio_device *adev = (struct audio_device *)dev;
3601 pthread_mutex_lock(&adev->lock);
3602 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003603 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003604 pthread_mutex_unlock(&adev->lock);
3605 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606}
3607
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003608static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3609 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610{
3611 return -ENOSYS;
3612}
3613
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003614static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3615 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616{
3617 return -ENOSYS;
3618}
3619
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003620static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3621 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622{
3623 return -ENOSYS;
3624}
3625
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003626static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3627 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628{
3629 return -ENOSYS;
3630}
3631
3632static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3633{
3634 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 pthread_mutex_lock(&adev->lock);
3637 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003638 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003640 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003641 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003642 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003643 adev->current_call_output = NULL;
3644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 }
3646 pthread_mutex_unlock(&adev->lock);
3647 return 0;
3648}
3649
3650static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3651{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003652 int ret;
3653
3654 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003655 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003656 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3657 pthread_mutex_unlock(&adev->lock);
3658
3659 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660}
3661
3662static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3663{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003664 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 return 0;
3666}
3667
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003668static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 const struct audio_config *config)
3670{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003671 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003673 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3674 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675}
3676
3677static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003678 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 audio_devices_t devices,
3680 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003681 struct audio_stream_in **stream_in,
3682 audio_input_flags_t flags __unused,
3683 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003684 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685{
3686 struct audio_device *adev = (struct audio_device *)dev;
3687 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003688 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003689 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003690 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 *stream_in = NULL;
3693 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3694 return -EINVAL;
3695
3696 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003697
3698 if (!in) {
3699 ALOGE("failed to allocate input stream");
3700 return -ENOMEM;
3701 }
3702
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303703 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003704 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3705 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003707 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003708 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 in->stream.common.get_sample_rate = in_get_sample_rate;
3711 in->stream.common.set_sample_rate = in_set_sample_rate;
3712 in->stream.common.get_buffer_size = in_get_buffer_size;
3713 in->stream.common.get_channels = in_get_channels;
3714 in->stream.common.get_format = in_get_format;
3715 in->stream.common.set_format = in_set_format;
3716 in->stream.common.standby = in_standby;
3717 in->stream.common.dump = in_dump;
3718 in->stream.common.set_parameters = in_set_parameters;
3719 in->stream.common.get_parameters = in_get_parameters;
3720 in->stream.common.add_audio_effect = in_add_audio_effect;
3721 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3722 in->stream.set_gain = in_set_gain;
3723 in->stream.read = in_read;
3724 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3725
3726 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003727 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 in->standby = 1;
3730 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003731 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003732 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
3734 /* Update config params with the requested sample rate and channels */
3735 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003736 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3737 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3738 is_low_latency = true;
3739#if LOW_LATENCY_CAPTURE_USE_CASE
3740 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3741#endif
3742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003745 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003747 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303748 if (adev->mode != AUDIO_MODE_IN_CALL) {
3749 ret = -EINVAL;
3750 goto err_open;
3751 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003752 if (config->sample_rate == 0)
3753 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3754 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3755 config->sample_rate != 8000) {
3756 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3757 ret = -EINVAL;
3758 goto err_open;
3759 }
3760 if (config->format == AUDIO_FORMAT_DEFAULT)
3761 config->format = AUDIO_FORMAT_PCM_16_BIT;
3762 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3763 config->format = AUDIO_FORMAT_PCM_16_BIT;
3764 ret = -EINVAL;
3765 goto err_open;
3766 }
3767
3768 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3769 in->config = pcm_config_afe_proxy_record;
3770 in->config.channels = channel_count;
3771 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303772 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3773 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003774 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003775 audio_extn_compr_cap_format_supported(config->format) &&
3776 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003777 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003778 } else {
3779 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003780 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003781 buffer_size = get_input_buffer_size(config->sample_rate,
3782 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003783 channel_count,
3784 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003785 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003786 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3787 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3788 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3789 (in->config.rate == 8000 || in->config.rate == 16000) &&
3790 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3791 voice_extn_compress_voip_open_input_stream(in);
3792 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003793 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003795 /* This stream could be for sound trigger lab,
3796 get sound trigger pcm if present */
3797 audio_extn_sound_trigger_check_and_get_session(in);
3798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003800 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003801 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
3803err_open:
3804 free(in);
3805 *stream_in = NULL;
3806 return ret;
3807}
3808
3809static void adev_close_input_stream(struct audio_hw_device *dev,
3810 struct audio_stream_in *stream)
3811{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003812 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003813 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003814 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303815
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303816 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003817
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303818 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003819 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303820
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003821 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303822 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003823 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303824 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003825 if (ret != 0)
3826 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3827 __func__, ret);
3828 } else
3829 in_standby(&stream->common);
3830
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003831 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003832 audio_extn_ssr_deinit();
3833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834
Mingming Yine62d7842013-10-25 16:26:03 -07003835 if(audio_extn_compr_cap_enabled() &&
3836 audio_extn_compr_cap_format_supported(in->config.format))
3837 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003838
Mingming Yinfd7607b2016-01-22 12:48:44 -08003839 if (in->is_st_session) {
3840 ALOGV("%s: sound trigger pcm stop lab", __func__);
3841 audio_extn_sound_trigger_stop_lab(in);
3842 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003843 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 return;
3845}
3846
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003847static int adev_dump(const audio_hw_device_t *device __unused,
3848 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849{
3850 return 0;
3851}
3852
3853static int adev_close(hw_device_t *device)
3854{
3855 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003856
3857 if (!adev)
3858 return 0;
3859
3860 pthread_mutex_lock(&adev_init_lock);
3861
3862 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003863 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003864 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003865 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003866 audio_route_free(adev->audio_route);
3867 free(adev->snd_dev_ref_cnt);
3868 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003869 if (adev->adm_deinit)
3870 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003871 free(device);
3872 adev = NULL;
3873 }
3874 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876 return 0;
3877}
3878
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003879/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3880 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3881 * just that it _might_ work.
3882 */
3883static int period_size_is_plausible_for_low_latency(int period_size)
3884{
3885 switch (period_size) {
3886 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003887 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003888 case 240:
3889 case 320:
3890 case 480:
3891 return 1;
3892 default:
3893 return 0;
3894 }
3895}
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897static int adev_open(const hw_module_t *module, const char *name,
3898 hw_device_t **device)
3899{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003900 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003902 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3904
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003905 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003906 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003907 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003908 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003909 ALOGD("%s: returning existing instance of adev", __func__);
3910 ALOGD("%s: exit", __func__);
3911 pthread_mutex_unlock(&adev_init_lock);
3912 return 0;
3913 }
3914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 adev = calloc(1, sizeof(struct audio_device));
3916
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003917 if (!adev) {
3918 pthread_mutex_unlock(&adev_init_lock);
3919 return -ENOMEM;
3920 }
3921
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003922 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3925 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3926 adev->device.common.module = (struct hw_module_t *)module;
3927 adev->device.common.close = adev_close;
3928
3929 adev->device.init_check = adev_init_check;
3930 adev->device.set_voice_volume = adev_set_voice_volume;
3931 adev->device.set_master_volume = adev_set_master_volume;
3932 adev->device.get_master_volume = adev_get_master_volume;
3933 adev->device.set_master_mute = adev_set_master_mute;
3934 adev->device.get_master_mute = adev_get_master_mute;
3935 adev->device.set_mode = adev_set_mode;
3936 adev->device.set_mic_mute = adev_set_mic_mute;
3937 adev->device.get_mic_mute = adev_get_mic_mute;
3938 adev->device.set_parameters = adev_set_parameters;
3939 adev->device.get_parameters = adev_get_parameters;
3940 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3941 adev->device.open_output_stream = adev_open_output_stream;
3942 adev->device.close_output_stream = adev_close_output_stream;
3943 adev->device.open_input_stream = adev_open_input_stream;
3944 adev->device.close_input_stream = adev_close_input_stream;
3945 adev->device.dump = adev_dump;
3946
3947 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003949 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003950 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003953 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003954 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003955 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003956 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003957 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003958 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003959 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303960 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303961 adev->perf_lock_opts[0] = 0x101;
3962 adev->perf_lock_opts[1] = 0x20E;
3963 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303964
3965 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3966 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003968 adev->platform = platform_init(adev);
3969 if (!adev->platform) {
3970 free(adev->snd_dev_ref_cnt);
3971 free(adev);
3972 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3973 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003974 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003975 return -EINVAL;
3976 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003977
Naresh Tanniru4c630392014-05-12 01:05:52 +05303978 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3979
Eric Laurentc4aef752013-09-12 17:45:53 -07003980 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3981 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3982 if (adev->visualizer_lib == NULL) {
3983 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3984 } else {
3985 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3986 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003987 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003988 "visualizer_hal_start_output");
3989 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003990 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003991 "visualizer_hal_stop_output");
3992 }
3993 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003994 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003995 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003996
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003997 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3998 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3999 if (adev->offload_effects_lib == NULL) {
4000 ALOGE("%s: DLOPEN failed for %s", __func__,
4001 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4002 } else {
4003 ALOGV("%s: DLOPEN successful for %s", __func__,
4004 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4005 adev->offload_effects_start_output =
4006 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4007 "offload_effects_bundle_hal_start_output");
4008 adev->offload_effects_stop_output =
4009 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4010 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004011 adev->offload_effects_set_hpx_state =
4012 (int (*)(bool))dlsym(adev->offload_effects_lib,
4013 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304014 adev->offload_effects_get_parameters =
4015 (void (*)(struct str_parms *, struct str_parms *))
4016 dlsym(adev->offload_effects_lib,
4017 "offload_effects_bundle_get_parameters");
4018 adev->offload_effects_set_parameters =
4019 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4020 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004021 }
4022 }
4023
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004024 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4025 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4026 if (adev->adm_lib == NULL) {
4027 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4028 } else {
4029 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4030 adev->adm_init = (adm_init_t)
4031 dlsym(adev->adm_lib, "adm_init");
4032 adev->adm_deinit = (adm_deinit_t)
4033 dlsym(adev->adm_lib, "adm_deinit");
4034 adev->adm_register_input_stream = (adm_register_input_stream_t)
4035 dlsym(adev->adm_lib, "adm_register_input_stream");
4036 adev->adm_register_output_stream = (adm_register_output_stream_t)
4037 dlsym(adev->adm_lib, "adm_register_output_stream");
4038 adev->adm_deregister_stream = (adm_deregister_stream_t)
4039 dlsym(adev->adm_lib, "adm_deregister_stream");
4040 adev->adm_request_focus = (adm_request_focus_t)
4041 dlsym(adev->adm_lib, "adm_request_focus");
4042 adev->adm_abandon_focus = (adm_abandon_focus_t)
4043 dlsym(adev->adm_lib, "adm_abandon_focus");
4044 }
4045 }
4046
Mingming Yin514a8bc2014-07-29 15:22:21 -07004047 adev->bt_wb_speech_enabled = false;
4048
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004049 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 *device = &adev->device.common;
4051
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004052 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4053 &adev->streams_output_cfg_list);
4054
Kiran Kandi910e1862013-10-29 13:29:42 -07004055 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004056
4057 char value[PROPERTY_VALUE_MAX];
4058 int trial;
4059 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4060 trial = atoi(value);
4061 if (period_size_is_plausible_for_low_latency(trial)) {
4062 pcm_config_low_latency.period_size = trial;
4063 pcm_config_low_latency.start_threshold = trial / 4;
4064 pcm_config_low_latency.avail_min = trial / 4;
4065 configured_low_latency_capture_period_size = trial;
4066 }
4067 }
4068 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4069 trial = atoi(value);
4070 if (period_size_is_plausible_for_low_latency(trial)) {
4071 configured_low_latency_capture_period_size = trial;
4072 }
4073 }
4074
vivek mehta446c3962015-09-14 10:57:35 -07004075 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004076 pthread_mutex_unlock(&adev_init_lock);
4077
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004078 if (adev->adm_init)
4079 adev->adm_data = adev->adm_init();
4080
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304081 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004082 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 return 0;
4084}
4085
4086static struct hw_module_methods_t hal_module_methods = {
4087 .open = adev_open,
4088};
4089
4090struct audio_module HAL_MODULE_INFO_SYM = {
4091 .common = {
4092 .tag = HARDWARE_MODULE_TAG,
4093 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4094 .hal_api_version = HARDWARE_HAL_API_VERSION,
4095 .id = AUDIO_HARDWARE_MODULE_ID,
4096 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004097 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098 .methods = &hal_module_methods,
4099 },
4100};