blob: 5bd6651b2c685aff94e6232947d36d093eafbae8 [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
vivek mehtaa76401a2015-04-24 14:12:15 -0700252__attribute__ ((visibility ("default")))
253bool audio_hw_send_gain_dep_calibration(int level) {
254 bool ret_val = false;
255 ALOGV("%s: called ... ", __func__);
256
257 pthread_mutex_lock(&adev_init_lock);
258
259 if (adev != NULL && adev->platform != NULL) {
260 pthread_mutex_lock(&adev->lock);
261 ret_val = platform_send_gain_dep_cal(adev->platform, level);
262 pthread_mutex_unlock(&adev->lock);
263 } else {
264 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
265 }
266
267 pthread_mutex_unlock(&adev_init_lock);
268
269 return ret_val;
270}
271
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800272static int check_and_set_gapless_mode(struct audio_device *adev) {
273
274
275 char value[PROPERTY_VALUE_MAX] = {0};
276 bool gapless_enabled = false;
277 const char *mixer_ctl_name = "Compress Gapless Playback";
278 struct mixer_ctl *ctl;
279
280 ALOGV("%s:", __func__);
281 property_get("audio.offload.gapless.enabled", value, NULL);
282 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
283
284 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
285 if (!ctl) {
286 ALOGE("%s: Could not get ctl for mixer cmd - %s",
287 __func__, mixer_ctl_name);
288 return -EINVAL;
289 }
290
291 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
292 ALOGE("%s: Could not set gapless mode %d",
293 __func__, gapless_enabled);
294 return -EINVAL;
295 }
296 return 0;
297}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700299static bool is_supported_format(audio_format_t format)
300{
Eric Laurent86e17132013-09-12 17:49:30 -0700301 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530302 format == AUDIO_FORMAT_AAC_LC ||
303 format == AUDIO_FORMAT_AAC_HE_V1 ||
304 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530305 format == AUDIO_FORMAT_AAC_ADTS_LC ||
306 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
307 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700309 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700310 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800311 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530312 format == AUDIO_FORMAT_ALAC ||
313 format == AUDIO_FORMAT_APE ||
314 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800315 format == AUDIO_FORMAT_WMA ||
316 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800317 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700318
319 return false;
320}
321
322static int get_snd_codec_id(audio_format_t format)
323{
324 int id = 0;
325
Ashish Jainf9b78162014-08-25 20:36:25 +0530326 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700327 case AUDIO_FORMAT_MP3:
328 id = SND_AUDIOCODEC_MP3;
329 break;
330 case AUDIO_FORMAT_AAC:
331 id = SND_AUDIOCODEC_AAC;
332 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530333 case AUDIO_FORMAT_AAC_ADTS:
334 id = SND_AUDIOCODEC_AAC;
335 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530336 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700337 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800338 id = SND_AUDIOCODEC_PCM;
339 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700340 case AUDIO_FORMAT_FLAC:
341 id = SND_AUDIOCODEC_FLAC;
342 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530343 case AUDIO_FORMAT_ALAC:
344 id = SND_AUDIOCODEC_ALAC;
345 break;
346 case AUDIO_FORMAT_APE:
347 id = SND_AUDIOCODEC_APE;
348 break;
349 case AUDIO_FORMAT_VORBIS:
350 id = SND_AUDIOCODEC_VORBIS;
351 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800352 case AUDIO_FORMAT_WMA:
353 id = SND_AUDIOCODEC_WMA;
354 break;
355 case AUDIO_FORMAT_WMA_PRO:
356 id = SND_AUDIOCODEC_WMA_PRO;
357 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700358 default:
Mingming Yin90310102013-11-13 16:57:00 -0800359 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 }
361
362 return id;
363}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800364
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530365int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530366{
367 int snd_scard_state;
368
369 if (!adev)
370 return SND_CARD_STATE_OFFLINE;
371
372 pthread_mutex_lock(&adev->snd_card_status.lock);
373 snd_scard_state = adev->snd_card_status.state;
374 pthread_mutex_unlock(&adev->snd_card_status.lock);
375
376 return snd_scard_state;
377}
378
379static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
380{
381 if (!adev)
382 return -ENOSYS;
383
384 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700385 if (adev->snd_card_status.state != snd_scard_state) {
386 adev->snd_card_status.state = snd_scard_state;
387 platform_snd_card_update(adev->platform, snd_scard_state);
388 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530389 pthread_mutex_unlock(&adev->snd_card_status.lock);
390
391 return 0;
392}
393
Avinash Vaish71a8b972014-07-24 15:36:33 +0530394static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
395 struct audio_usecase *uc_info)
396{
397 struct listnode *node;
398 struct audio_usecase *usecase;
399
400 if (uc_info == NULL)
401 return -EINVAL;
402
403 /* Re-route all voice usecases on the shared backend other than the
404 specified usecase to new snd devices */
405 list_for_each(node, &adev->usecase_list) {
406 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800407 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530408 enable_audio_route(adev, usecase);
409 }
410 return 0;
411}
412
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700413int pcm_ioctl(struct pcm *pcm, int request, ...)
414{
415 va_list ap;
416 void * arg;
417 int pcm_fd = *(int*)pcm;
418
419 va_start(ap, request);
420 arg = va_arg(ap, void *);
421 va_end(ap);
422
423 return ioctl(pcm_fd, request, arg);
424}
425
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700426int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700427 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800428{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700429 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700430 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800431
432 if (usecase == NULL)
433 return -EINVAL;
434
435 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
436
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800437 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700438 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800442#ifdef DS1_DOLBY_DAP_ENABLED
443 audio_extn_dolby_set_dmid(adev);
444 audio_extn_dolby_set_endpoint(adev);
445#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700446 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700447 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530448 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700449 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530450 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800451 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700452 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700453 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700454 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800455 ALOGV("%s: exit", __func__);
456 return 0;
457}
458
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700459int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700460 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700462 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700463 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800464
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530465 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466 return -EINVAL;
467
468 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469 if (usecase->type == PCM_CAPTURE)
470 snd_device = usecase->in_snd_device;
471 else
472 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800473 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700474 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700475 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700476 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700477 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530478 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800479 ALOGV("%s: exit", __func__);
480 return 0;
481}
482
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700483int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700484 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800485{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530486 int i, num_devices = 0;
487 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
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 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530532 } else if (platform_can_split_snd_device(adev->platform, snd_device,
533 &num_devices, new_snd_devices)) {
534 for (i = 0; i < num_devices; i++) {
535 enable_snd_device(adev, new_snd_devices[i]);
536 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800537 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700538 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700539 /* due to the possibility of calibration overwrite between listen
540 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700541 audio_extn_sound_trigger_update_device_status(snd_device,
542 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530543 audio_extn_listen_update_device_status(snd_device,
544 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700545 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700547 audio_extn_sound_trigger_update_device_status(snd_device,
548 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530549 audio_extn_listen_update_device_status(snd_device,
550 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700551 return -EINVAL;
552 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300553 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700554 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530555
556 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
557 !adev->native_playback_enabled &&
558 audio_is_true_native_stream_active(adev)) {
559 ALOGD("%s: %d: napb: enabling native mode in hardware",
560 __func__, __LINE__);
561 audio_route_apply_and_update_path(adev->audio_route,
562 "true-native-mode");
563 adev->native_playback_enabled = true;
564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566 return 0;
567}
568
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700569int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700570 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800571{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530572 int i, num_devices = 0;
573 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700574 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
575
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800576 if (snd_device < SND_DEVICE_MIN ||
577 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800578 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800579 return -EINVAL;
580 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
582 ALOGE("%s: device ref cnt is already 0", __func__);
583 return -EINVAL;
584 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700587
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700588 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
589 ALOGE("%s: Invalid sound device returned", __func__);
590 return -EINVAL;
591 }
592
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700594 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800595 /* exit usb play back thread */
596 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
597 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
598 audio_extn_usb_stop_playback();
599
600 /* exit usb capture thread */
601 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700602 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800603
604 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
605 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700606 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530607 } else if (platform_can_split_snd_device(adev->platform, snd_device,
608 &num_devices, new_snd_devices)) {
609 for (i = 0; i < num_devices; i++) {
610 disable_snd_device(adev, new_snd_devices[i]);
611 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300612 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700613 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300614 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700615
Ashish Jain81eb2a82015-05-13 10:52:34 +0530616 if (snd_device == SND_DEVICE_OUT_HDMI)
617 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530618 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
619 adev->native_playback_enabled) {
620 ALOGD("%s: %d: napb: disabling native mode in hardware",
621 __func__, __LINE__);
622 audio_route_reset_and_update_path(adev->audio_route,
623 "true-native-mode");
624 adev->native_playback_enabled = false;
625 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530626
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200627 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700628 audio_extn_sound_trigger_update_device_status(snd_device,
629 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530630 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800631 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700632 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800634 return 0;
635}
636
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530638 struct audio_usecase *uc_info,
639 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640{
641 struct listnode *node;
642 struct audio_usecase *usecase;
643 bool switch_device[AUDIO_USECASE_MAX];
644 int i, num_uc_to_switch = 0;
645
646 /*
647 * This function is to make sure that all the usecases that are active on
648 * the hardware codec backend are always routed to any one device that is
649 * handled by the hardware codec.
650 * For example, if low-latency and deep-buffer usecases are currently active
651 * on speaker and out_set_parameters(headset) is received on low-latency
652 * output, then we have to make sure deep-buffer is also switched to headset,
653 * because of the limitation that both the devices cannot be enabled
654 * at the same time as they share the same backend.
655 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700656 /*
657 * This call is to check if we need to force routing for a particular stream
658 * If there is a backend configuration change for the device when a
659 * new stream starts, then ADM needs to be closed and re-opened with the new
660 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800661 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700662 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800663 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
664 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530665
666 ALOGD("%s:becf: force routing %d", __func__, force_routing);
667
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800669 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800670 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 for (i = 0; i < AUDIO_USECASE_MAX; i++)
672 switch_device[i] = false;
673
674 list_for_each(node, &adev->usecase_list) {
675 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800676
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530677 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
678 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530679 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530680 platform_get_snd_device_name(usecase->out_snd_device),
681 platform_check_backends_match(snd_device, usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800682
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800683 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530684 usecase != uc_info &&
685 (usecase->out_snd_device != snd_device || force_routing) &&
686 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
687 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
688 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
689 __func__, use_case_table[usecase->id],
690 platform_get_snd_device_name(usecase->out_snd_device));
691 disable_audio_route(adev, usecase);
692 switch_device[usecase->id] = true;
693 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 }
695 }
696
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530697 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
698 num_uc_to_switch);
699
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700700 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700701 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700702
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530703 /* Make sure the previous devices to be disabled first and then enable the
704 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 list_for_each(node, &adev->usecase_list) {
706 usecase = node_to_item(node, struct audio_usecase, list);
707 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700708 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 }
710 }
711
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700712 list_for_each(node, &adev->usecase_list) {
713 usecase = node_to_item(node, struct audio_usecase, list);
714 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700715 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700716 }
717 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700718
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 /* Re-route all the usecases on the shared backend other than the
720 specified usecase to new snd devices */
721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530723 /* Update the out_snd_device only before enabling the audio route */
724 if (switch_device[usecase->id]) {
725 usecase->out_snd_device = snd_device;
726 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530727 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530728 use_case_table[usecase->id],
729 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530730 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530731 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700732 }
733 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700734 }
735}
736
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737static void check_and_route_capture_usecases(struct audio_device *adev,
738 struct audio_usecase *uc_info,
739 snd_device_t snd_device)
740{
741 struct listnode *node;
742 struct audio_usecase *usecase;
743 bool switch_device[AUDIO_USECASE_MAX];
744 int i, num_uc_to_switch = 0;
745
746 /*
747 * This function is to make sure that all the active capture usecases
748 * are always routed to the same input sound device.
749 * For example, if audio-record and voice-call usecases are currently
750 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
751 * is received for voice call then we have to make sure that audio-record
752 * usecase is also switched to earpiece i.e. voice-dmic-ef,
753 * because of the limitation that two devices cannot be enabled
754 * at the same time if they share the same backend.
755 */
756 for (i = 0; i < AUDIO_USECASE_MAX; i++)
757 switch_device[i] = false;
758
759 list_for_each(node, &adev->usecase_list) {
760 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800761 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700762 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700763 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700764 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530765 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
766 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700767 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700768 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
769 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700770 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700771 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700772 switch_device[usecase->id] = true;
773 num_uc_to_switch++;
774 }
775 }
776
777 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700778 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700779
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530780 /* Make sure the previous devices to be disabled first and then enable the
781 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700782 list_for_each(node, &adev->usecase_list) {
783 usecase = node_to_item(node, struct audio_usecase, list);
784 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700785 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800786 }
787 }
788
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
791 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700792 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700793 }
794 }
795
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700796 /* Re-route all the usecases on the shared backend other than the
797 specified usecase to new snd devices */
798 list_for_each(node, &adev->usecase_list) {
799 usecase = node_to_item(node, struct audio_usecase, list);
800 /* Update the in_snd_device only before enabling the audio route */
801 if (switch_device[usecase->id] ) {
802 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800803 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530804 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700805 }
806 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 }
808}
809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700811static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700813 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700814 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815
816 switch (channels) {
817 /*
818 * Do not handle stereo output in Multi-channel cases
819 * Stereo case is handled in normal playback path
820 */
821 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700822 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
823 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
824 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828 break;
829 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700830 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
831 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
832 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
833 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
834 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
835 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
836 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 break;
838 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700839 ALOGE("HDMI does not support multi channel playback");
840 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841 break;
842 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700843 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800844}
845
Alexy Josephb1379942016-01-29 15:49:38 -0800846audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800847 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700848{
849 struct audio_usecase *usecase;
850 struct listnode *node;
851
852 list_for_each(node, &adev->usecase_list) {
853 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800854 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700855 ALOGV("%s: usecase id %d", __func__, usecase->id);
856 return usecase->id;
857 }
858 }
859 return USECASE_INVALID;
860}
861
Alexy Josephb1379942016-01-29 15:49:38 -0800862struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700863 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864{
865 struct audio_usecase *usecase;
866 struct listnode *node;
867
868 list_for_each(node, &adev->usecase_list) {
869 usecase = node_to_item(node, struct audio_usecase, list);
870 if (usecase->id == uc_id)
871 return usecase;
872 }
873 return NULL;
874}
875
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530876/*
877 * is a true native playback active
878 */
879bool audio_is_true_native_stream_active(struct audio_device *adev)
880{
881 bool active = false;
882 int i = 0;
883 struct listnode *node;
884
885 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
886 ALOGV("%s:napb: not in true mode or non hdphones device",
887 __func__);
888 active = false;
889 goto exit;
890 }
891
892 list_for_each(node, &adev->usecase_list) {
893 struct audio_usecase *uc;
894 uc = node_to_item(node, struct audio_usecase, list);
895 struct stream_out *curr_out =
896 (struct stream_out*) uc->stream.out;
897
898 if (curr_out && PCM_PLAYBACK == uc->type) {
899 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
900 "(%d) device %s", __func__, i++, use_case_table[uc->id],
901 uc->id, curr_out->sample_rate,
902 curr_out->bit_width,
903 platform_get_snd_device_name(uc->out_snd_device));
904
905 if (is_offload_usecase(uc->id) &&
906 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
907 active = true;
908 ALOGD("%s:napb:native stream detected", __func__);
909 }
910 }
911 }
912exit:
913 return active;
914}
915
916
917static bool force_device_switch(struct audio_usecase *usecase)
918{
919 bool ret = false;
920 bool is_it_true_mode = false;
921
922 if (is_offload_usecase(usecase->id) &&
923 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800924 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
925 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
926 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530927 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
928 if ((is_it_true_mode && !adev->native_playback_enabled) ||
929 (!is_it_true_mode && adev->native_playback_enabled)){
930 ret = true;
931 ALOGD("napb: time to toggle native mode");
932 }
933 }
934
935 return ret;
936}
937
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700938int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800939{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800940 snd_device_t out_snd_device = SND_DEVICE_NONE;
941 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 struct audio_usecase *usecase = NULL;
943 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800944 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800945 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800946 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530949 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
950
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951 usecase = get_usecase_from_list(adev, uc_id);
952 if (usecase == NULL) {
953 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
954 return -EINVAL;
955 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800957 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800958 (usecase->type == VOIP_CALL) ||
959 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700960 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800961 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700962 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 usecase->devices = usecase->stream.out->devices;
964 } else {
965 /*
966 * If the voice call is active, use the sound devices of voice call usecase
967 * so that it would not result any device switch. All the usecases will
968 * be switched to new device when select_devices() is called for voice call
969 * usecase. This is to avoid switching devices for voice call when
970 * check_usecases_codec_backend() is called below.
971 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800972 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700973 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800974 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700975 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
976 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 in_snd_device = vc_usecase->in_snd_device;
978 out_snd_device = vc_usecase->out_snd_device;
979 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800980 } else if (voice_extn_compress_voip_is_active(adev)) {
981 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700982 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530983 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700984 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800985 in_snd_device = voip_usecase->in_snd_device;
986 out_snd_device = voip_usecase->out_snd_device;
987 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800988 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800989 hfp_ucid = audio_extn_hfp_get_usecase();
990 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700991 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800992 in_snd_device = hfp_usecase->in_snd_device;
993 out_snd_device = hfp_usecase->out_snd_device;
994 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700995 }
996 if (usecase->type == PCM_PLAYBACK) {
997 usecase->devices = usecase->stream.out->devices;
998 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700999 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001000 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001001 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001002 if (usecase->stream.out == adev->primary_output &&
1003 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001004 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001005 select_devices(adev, adev->active_input->usecase);
1006 }
1007 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008 } else if (usecase->type == PCM_CAPTURE) {
1009 usecase->devices = usecase->stream.in->device;
1010 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001011 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001012 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001013 if (adev->active_input &&
1014 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301015 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1016 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1017 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001018 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001019 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001020 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1021 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001022 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001023 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001024 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001025 }
1026 }
1027
1028 if (out_snd_device == usecase->out_snd_device &&
1029 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301030
1031 if (!force_device_switch(usecase))
1032 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 }
1034
sangwoobc677242013-08-08 16:53:43 +09001035 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001036 out_snd_device, platform_get_snd_device_name(out_snd_device),
1037 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 /*
1040 * Limitation: While in call, to do a device switch we need to disable
1041 * and enable both RX and TX devices though one of them is same as current
1042 * device.
1043 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001044 if ((usecase->type == VOICE_CALL) &&
1045 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1046 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001047 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001048 }
1049
1050 if (((usecase->type == VOICE_CALL) ||
1051 (usecase->type == VOIP_CALL)) &&
1052 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1053 /* Disable sidetone only if voice/voip call already exists */
1054 if (voice_is_call_state_active(adev) ||
1055 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001056 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001057 }
1058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 /* Disable current sound devices */
1060 if (usecase->out_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->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 }
1064
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001065 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001066 disable_audio_route(adev, usecase);
1067 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 }
1069
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001070 /* Applicable only on the targets that has external modem.
1071 * New device information should be sent to modem before enabling
1072 * the devices to reduce in-call device switch time.
1073 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001074 if ((usecase->type == VOICE_CALL) &&
1075 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1076 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001077 status = platform_switch_voice_call_enable_device_config(adev->platform,
1078 out_snd_device,
1079 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001080 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001081
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 /* Enable new sound devices */
1083 if (out_snd_device != SND_DEVICE_NONE) {
1084 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1085 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087 }
1088
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001089 if (in_snd_device != SND_DEVICE_NONE) {
1090 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001091 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001092 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001093
Avinash Vaish71a8b972014-07-24 15:36:33 +05301094 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001095 status = platform_switch_voice_call_device_post(adev->platform,
1096 out_snd_device,
1097 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301098 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001099 /* Enable sidetone only if voice/voip call already exists */
1100 if (voice_is_call_state_active(adev) ||
1101 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001102 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301103 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001104
sangwoo170731f2013-06-08 15:36:36 +09001105 usecase->in_snd_device = in_snd_device;
1106 usecase->out_snd_device = out_snd_device;
1107
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301108 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001109 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301110 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001111 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301112 usecase->stream.out->flags,
1113 usecase->stream.out->format,
1114 usecase->stream.out->sample_rate,
1115 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301116 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301117 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001118 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301119 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001120
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001121 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001122
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001123 /* Applicable only on the targets that has external modem.
1124 * Enable device command should be sent to modem only after
1125 * enabling voice call mixer controls
1126 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001127 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001128 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1129 out_snd_device,
1130 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301131 ALOGD("%s: done",__func__);
1132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133 return status;
1134}
1135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136static int stop_input_stream(struct stream_in *in)
1137{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301138 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 struct audio_usecase *uc_info;
1140 struct audio_device *adev = in->dev;
1141
Eric Laurentc8400632013-02-14 19:04:54 -08001142 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001143
Eric Laurent994a6932013-07-17 11:51:42 -07001144 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001146 uc_info = get_usecase_from_list(adev, in->usecase);
1147 if (uc_info == NULL) {
1148 ALOGE("%s: Could not find the usecase (%d) in the list",
1149 __func__, in->usecase);
1150 return -EINVAL;
1151 }
1152
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001153 /* Close in-call recording streams */
1154 voice_check_and_stop_incall_rec_usecase(adev, in);
1155
Eric Laurent150dbfe2013-02-27 14:31:02 -08001156 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001157 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158
1159 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001160 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001162 list_remove(&uc_info->list);
1163 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164
Eric Laurent994a6932013-07-17 11:51:42 -07001165 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166 return ret;
1167}
1168
1169int start_input_stream(struct stream_in *in)
1170{
1171 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001172 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173 struct audio_usecase *uc_info;
1174 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301175 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176
Mingming Yin2664a5b2015-09-03 10:53:11 -07001177 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1178 if (get_usecase_from_list(adev, usecase) == NULL)
1179 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301180 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1181 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001182
Naresh Tanniru80659832014-06-04 18:17:56 +05301183
1184 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301185 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301186 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301187 goto error_config;
1188 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301189
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001190 /* Check if source matches incall recording usecase criteria */
1191 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1192 if (ret)
1193 goto error_config;
1194 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001195 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1196
1197 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1198 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1199 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1200 goto error_config;
1201 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001202
Eric Laurentb23d5282013-05-14 15:27:20 -07001203 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001204 if (in->pcm_device_id < 0) {
1205 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1206 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001207 ret = -EINVAL;
1208 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210
1211 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001213
1214 if (!uc_info) {
1215 ret = -ENOMEM;
1216 goto error_config;
1217 }
1218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219 uc_info->id = in->usecase;
1220 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001221 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001222 uc_info->devices = in->device;
1223 uc_info->in_snd_device = SND_DEVICE_NONE;
1224 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001226 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301227 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1228 adev->perf_lock_opts,
1229 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001230 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231
Eric Laurentc8400632013-02-14 19:04:54 -08001232 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001233 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1234
1235 unsigned int flags = PCM_IN;
1236 unsigned int pcm_open_retry_count = 0;
1237
1238 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1239 flags |= PCM_MMAP | PCM_NOIRQ;
1240 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1241 }
1242
1243 while (1) {
1244 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1245 flags, &in->config);
1246 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1247 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1248 if (in->pcm != NULL) {
1249 pcm_close(in->pcm);
1250 in->pcm = NULL;
1251 }
1252 if (pcm_open_retry_count-- == 0) {
1253 ret = -EIO;
1254 goto error_open;
1255 }
1256 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1257 continue;
1258 }
1259 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001260 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001261
1262 ALOGV("%s: pcm_prepare", __func__);
1263 ret = pcm_prepare(in->pcm);
1264 if (ret < 0) {
1265 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1266 pcm_close(in->pcm);
1267 in->pcm = NULL;
1268 goto error_open;
1269 }
1270
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301271 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001272 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001273
Eric Laurentc8400632013-02-14 19:04:54 -08001274 return ret;
1275
1276error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301277 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001279error_config:
1280 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301281 /*
1282 * sleep 50ms to allow sufficient time for kernel
1283 * drivers to recover incases like SSR.
1284 */
1285 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001287
1288 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289}
1290
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001291void lock_input_stream(struct stream_in *in)
1292{
1293 pthread_mutex_lock(&in->pre_lock);
1294 pthread_mutex_lock(&in->lock);
1295 pthread_mutex_unlock(&in->pre_lock);
1296}
1297
1298void lock_output_stream(struct stream_out *out)
1299{
1300 pthread_mutex_lock(&out->pre_lock);
1301 pthread_mutex_lock(&out->lock);
1302 pthread_mutex_unlock(&out->pre_lock);
1303}
1304
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001305/* must be called with out->lock locked */
1306static int send_offload_cmd_l(struct stream_out* out, int command)
1307{
1308 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1309
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001310 if (!cmd) {
1311 ALOGE("failed to allocate mem for command 0x%x", command);
1312 return -ENOMEM;
1313 }
1314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 ALOGVV("%s %d", __func__, command);
1316
1317 cmd->cmd = command;
1318 list_add_tail(&out->offload_cmd_list, &cmd->node);
1319 pthread_cond_signal(&out->offload_cond);
1320 return 0;
1321}
1322
1323/* must be called iwth out->lock locked */
1324static void stop_compressed_output_l(struct stream_out *out)
1325{
1326 out->offload_state = OFFLOAD_STATE_IDLE;
1327 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001328 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 if (out->compr != NULL) {
1330 compress_stop(out->compr);
1331 while (out->offload_thread_blocked) {
1332 pthread_cond_wait(&out->cond, &out->lock);
1333 }
1334 }
1335}
1336
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001337bool is_offload_usecase(audio_usecase_t uc_id)
1338{
1339 unsigned int i;
1340 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1341 if (uc_id == offload_usecases[i])
1342 return true;
1343 }
1344 return false;
1345}
1346
vivek mehta446c3962015-09-14 10:57:35 -07001347static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001348{
vivek mehta446c3962015-09-14 10:57:35 -07001349 audio_usecase_t ret_uc = USECASE_INVALID;
1350 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001351 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001352 if (!adev->multi_offload_enable) {
1353 if (is_direct_pcm)
1354 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1355 else
1356 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001357
vivek mehta446c3962015-09-14 10:57:35 -07001358 pthread_mutex_lock(&adev->lock);
1359 if (get_usecase_from_list(adev, ret_uc) != NULL)
1360 ret_uc = USECASE_INVALID;
1361 pthread_mutex_unlock(&adev->lock);
1362
1363 return ret_uc;
1364 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001365
1366 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001367 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1368 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1369 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1370 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001371 break;
1372 }
1373 }
vivek mehta446c3962015-09-14 10:57:35 -07001374
1375 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1376 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001377}
1378
1379static void free_offload_usecase(struct audio_device *adev,
1380 audio_usecase_t uc_id)
1381{
vivek mehta446c3962015-09-14 10:57:35 -07001382 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001383 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001384
1385 if (!adev->multi_offload_enable)
1386 return;
1387
1388 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1389 if (offload_usecases[offload_uc_index] == uc_id) {
1390 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001391 break;
1392 }
1393 }
1394 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1395}
1396
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001397static void *offload_thread_loop(void *context)
1398{
1399 struct stream_out *out = (struct stream_out *) context;
1400 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001401 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001402
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001403 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1404 set_sched_policy(0, SP_FOREGROUND);
1405 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1406
1407 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001408 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001409 for (;;) {
1410 struct offload_cmd *cmd = NULL;
1411 stream_callback_event_t event;
1412 bool send_callback = false;
1413
1414 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1415 __func__, list_empty(&out->offload_cmd_list),
1416 out->offload_state);
1417 if (list_empty(&out->offload_cmd_list)) {
1418 ALOGV("%s SLEEPING", __func__);
1419 pthread_cond_wait(&out->offload_cond, &out->lock);
1420 ALOGV("%s RUNNING", __func__);
1421 continue;
1422 }
1423
1424 item = list_head(&out->offload_cmd_list);
1425 cmd = node_to_item(item, struct offload_cmd, node);
1426 list_remove(item);
1427
1428 ALOGVV("%s STATE %d CMD %d out->compr %p",
1429 __func__, out->offload_state, cmd->cmd, out->compr);
1430
1431 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1432 free(cmd);
1433 break;
1434 }
1435
1436 if (out->compr == NULL) {
1437 ALOGE("%s: Compress handle is NULL", __func__);
1438 pthread_cond_signal(&out->cond);
1439 continue;
1440 }
1441 out->offload_thread_blocked = true;
1442 pthread_mutex_unlock(&out->lock);
1443 send_callback = false;
1444 switch(cmd->cmd) {
1445 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001446 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001447 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001448 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 send_callback = true;
1450 event = STREAM_CBK_EVENT_WRITE_READY;
1451 break;
1452 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001453 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301454 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001455 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301456 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001457 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301458 if (ret < 0)
1459 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301460 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301461 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001462 compress_drain(out->compr);
1463 else
1464 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301465 if (ret != -ENETRESET) {
1466 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301467 pthread_mutex_lock(&out->lock);
1468 out->send_new_metadata = 1;
1469 out->send_next_track_params = true;
1470 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301471 event = STREAM_CBK_EVENT_DRAIN_READY;
1472 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1473 } else
1474 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001475 break;
1476 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001477 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001478 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001479 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480 send_callback = true;
1481 event = STREAM_CBK_EVENT_DRAIN_READY;
1482 break;
1483 default:
1484 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1485 break;
1486 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001487 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001488 out->offload_thread_blocked = false;
1489 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001490 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001491 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001492 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001493 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001494 free(cmd);
1495 }
1496
1497 pthread_cond_signal(&out->cond);
1498 while (!list_empty(&out->offload_cmd_list)) {
1499 item = list_head(&out->offload_cmd_list);
1500 list_remove(item);
1501 free(node_to_item(item, struct offload_cmd, node));
1502 }
1503 pthread_mutex_unlock(&out->lock);
1504
1505 return NULL;
1506}
1507
1508static int create_offload_callback_thread(struct stream_out *out)
1509{
1510 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1511 list_init(&out->offload_cmd_list);
1512 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1513 offload_thread_loop, out);
1514 return 0;
1515}
1516
1517static int destroy_offload_callback_thread(struct stream_out *out)
1518{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001519 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001520 stop_compressed_output_l(out);
1521 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1522
1523 pthread_mutex_unlock(&out->lock);
1524 pthread_join(out->offload_thread, (void **) NULL);
1525 pthread_cond_destroy(&out->offload_cond);
1526
1527 return 0;
1528}
1529
Eric Laurent07eeafd2013-10-06 12:52:49 -07001530static bool allow_hdmi_channel_config(struct audio_device *adev)
1531{
1532 struct listnode *node;
1533 struct audio_usecase *usecase;
1534 bool ret = true;
1535
1536 list_for_each(node, &adev->usecase_list) {
1537 usecase = node_to_item(node, struct audio_usecase, list);
1538 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1539 /*
1540 * If voice call is already existing, do not proceed further to avoid
1541 * disabling/enabling both RX and TX devices, CSD calls, etc.
1542 * Once the voice call done, the HDMI channels can be configured to
1543 * max channels of remaining use cases.
1544 */
1545 if (usecase->id == USECASE_VOICE_CALL) {
1546 ALOGD("%s: voice call is active, no change in HDMI channels",
1547 __func__);
1548 ret = false;
1549 break;
1550 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1551 ALOGD("%s: multi channel playback is active, "
1552 "no change in HDMI channels", __func__);
1553 ret = false;
1554 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001555 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001556 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001557 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1558 ", no change in HDMI channels", __func__,
1559 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001560 ret = false;
1561 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001562 }
1563 }
1564 }
1565 return ret;
1566}
1567
1568static int check_and_set_hdmi_channels(struct audio_device *adev,
1569 unsigned int channels)
1570{
1571 struct listnode *node;
1572 struct audio_usecase *usecase;
1573
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001574 unsigned int supported_channels = platform_edid_get_max_channels(
1575 adev->platform);
1576 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 /* Check if change in HDMI channel config is allowed */
1578 if (!allow_hdmi_channel_config(adev))
1579 return 0;
1580
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001581 if (channels > supported_channels)
1582 channels = supported_channels;
1583
Eric Laurent07eeafd2013-10-06 12:52:49 -07001584 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001585 ALOGD("%s: Requested channels are same as current channels(%d)",
1586 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001587 return 0;
1588 }
1589
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001590 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001591 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001592 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001593 adev->cur_hdmi_channels = channels;
1594
1595 /*
1596 * Deroute all the playback streams routed to HDMI so that
1597 * the back end is deactivated. Note that backend will not
1598 * be deactivated if any one stream is connected to it.
1599 */
1600 list_for_each(node, &adev->usecase_list) {
1601 usecase = node_to_item(node, struct audio_usecase, list);
1602 if (usecase->type == PCM_PLAYBACK &&
1603 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001605 }
1606 }
1607
1608 /*
1609 * Enable all the streams disabled above. Now the HDMI backend
1610 * will be activated with new channel configuration
1611 */
1612 list_for_each(node, &adev->usecase_list) {
1613 usecase = node_to_item(node, struct audio_usecase, list);
1614 if (usecase->type == PCM_PLAYBACK &&
1615 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001616 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001617 }
1618 }
1619
1620 return 0;
1621}
1622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623static int stop_output_stream(struct stream_out *out)
1624{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301625 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 struct audio_usecase *uc_info;
1627 struct audio_device *adev = out->dev;
1628
Eric Laurent994a6932013-07-17 11:51:42 -07001629 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631 uc_info = get_usecase_from_list(adev, out->usecase);
1632 if (uc_info == NULL) {
1633 ALOGE("%s: Could not find the usecase (%d) in the list",
1634 __func__, out->usecase);
1635 return -EINVAL;
1636 }
1637
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001638 if (is_offload_usecase(out->usecase) &&
1639 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001640 if (adev->visualizer_stop_output != NULL)
1641 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001642
1643 audio_extn_dts_remove_state_notifier_node(out->usecase);
1644
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001645 if (adev->offload_effects_stop_output != NULL)
1646 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1647 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001648
Eric Laurent150dbfe2013-02-27 14:31:02 -08001649 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001650 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001651
1652 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001653 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001655 list_remove(&uc_info->list);
1656 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001658 if (is_offload_usecase(out->usecase) &&
1659 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1660 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1661 ALOGV("Disable passthrough , reset mixer to pcm");
1662 /* NO_PASSTHROUGH */
1663 out->compr_config.codec->compr_passthr = 0;
1664 audio_extn_dolby_set_hdmi_config(adev, out);
1665 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1666 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001667 /* Must be called after removing the usecase from list */
1668 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1669 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1670
Eric Laurent994a6932013-07-17 11:51:42 -07001671 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 return ret;
1673}
1674
1675int start_output_stream(struct stream_out *out)
1676{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001678 int sink_channels = 0;
1679 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680 struct audio_usecase *uc_info;
1681 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301682 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001684 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1685 ret = -EINVAL;
1686 goto error_config;
1687 }
1688
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301689 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1690 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1691 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301692
Naresh Tanniru80659832014-06-04 18:17:56 +05301693 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301694 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301695 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301696 goto error_config;
1697 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301698
Eric Laurentb23d5282013-05-14 15:27:20 -07001699 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700 if (out->pcm_device_id < 0) {
1701 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1702 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001703 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001704 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 }
1706
1707 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001708
1709 if (!uc_info) {
1710 ret = -ENOMEM;
1711 goto error_config;
1712 }
1713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714 uc_info->id = out->usecase;
1715 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001716 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001717 uc_info->devices = out->devices;
1718 uc_info->in_snd_device = SND_DEVICE_NONE;
1719 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001720 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001721 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001722 if (is_offload_usecase(out->usecase)) {
1723 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001724 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1725 }
1726 }
Mingming Yin9c041392014-05-01 15:37:31 -07001727 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1728 if (!strncmp("true", prop_value, 4)) {
1729 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001730 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1731 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001732 check_and_set_hdmi_channels(adev, sink_channels);
1733 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001734 if (is_offload_usecase(out->usecase)) {
1735 unsigned int ch_count = out->compr_config.codec->ch_in;
1736 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1737 /* backend channel config for passthrough stream is stereo */
1738 ch_count = 2;
1739 check_and_set_hdmi_channels(adev, ch_count);
1740 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001741 check_and_set_hdmi_channels(adev, out->config.channels);
1742 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001743 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001744 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001745 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301747 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1748 adev->perf_lock_opts,
1749 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001750 select_devices(adev, out->usecase);
1751
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001752 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1753 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001754 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001755 unsigned int flags = PCM_OUT;
1756 unsigned int pcm_open_retry_count = 0;
1757 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1758 flags |= PCM_MMAP | PCM_NOIRQ;
1759 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1760 } else
1761 flags |= PCM_MONOTONIC;
1762
1763 while (1) {
1764 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1765 flags, &out->config);
1766 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1767 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1768 if (out->pcm != NULL) {
1769 pcm_close(out->pcm);
1770 out->pcm = NULL;
1771 }
1772 if (pcm_open_retry_count-- == 0) {
1773 ret = -EIO;
1774 goto error_open;
1775 }
1776 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1777 continue;
1778 }
1779 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001781
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001782 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1783 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001784
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001785 ALOGV("%s: pcm_prepare", __func__);
1786 if (pcm_is_ready(out->pcm)) {
1787 ret = pcm_prepare(out->pcm);
1788 if (ret < 0) {
1789 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1790 pcm_close(out->pcm);
1791 out->pcm = NULL;
1792 goto error_open;
1793 }
1794 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001796 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1797 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001799 out->compr = compress_open(adev->snd_card,
1800 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001801 COMPRESS_IN, &out->compr_config);
1802 if (out->compr && !is_compress_ready(out->compr)) {
1803 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1804 compress_close(out->compr);
1805 out->compr = NULL;
1806 ret = -EIO;
1807 goto error_open;
1808 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301809 /* compress_open sends params of the track, so reset the flag here */
1810 out->is_compr_metadata_avail = false;
1811
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 if (out->offload_callback)
1813 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001814
Fred Oh3f43e742015-03-04 18:42:34 -08001815 /* Since small bufs uses blocking writes, a write will be blocked
1816 for the default max poll time (20s) in the event of an SSR.
1817 Reduce the poll time to observe and deal with SSR faster.
1818 */
1819 if (out->use_small_bufs) {
1820 compress_set_max_poll_wait(out->compr, 1000);
1821 }
1822
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001823 audio_extn_dts_create_state_notifier_node(out->usecase);
1824 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1825 popcount(out->channel_mask),
1826 out->playback_started);
1827
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001828#ifdef DS1_DOLBY_DDP_ENABLED
1829 if (audio_extn_is_dolby_format(out->format))
1830 audio_extn_dolby_send_ddp_endp_params(adev);
1831#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001832 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1833 if (adev->visualizer_start_output != NULL)
1834 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1835 if (adev->offload_effects_start_output != NULL)
1836 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001837 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301840 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001841 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001844error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301845 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001847error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301848 /*
1849 * sleep 50ms to allow sufficient time for kernel
1850 * drivers to recover incases like SSR.
1851 */
1852 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001853 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854}
1855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856static int check_input_parameters(uint32_t sample_rate,
1857 audio_format_t format,
1858 int channel_count)
1859{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001860 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001862 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001863 !voice_extn_compress_voip_is_format_supported(format) &&
1864 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001865
1866 switch (channel_count) {
1867 case 1:
1868 case 2:
1869 case 6:
1870 break;
1871 default:
1872 ret = -EINVAL;
1873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874
1875 switch (sample_rate) {
1876 case 8000:
1877 case 11025:
1878 case 12000:
1879 case 16000:
1880 case 22050:
1881 case 24000:
1882 case 32000:
1883 case 44100:
1884 case 48000:
1885 break;
1886 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001887 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 }
1889
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001890 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891}
1892
1893static size_t get_input_buffer_size(uint32_t sample_rate,
1894 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001895 int channel_count,
1896 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897{
1898 size_t size = 0;
1899
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001900 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1901 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001903 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001904 if (is_low_latency)
1905 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001906 /* ToDo: should use frame_size computed based on the format and
1907 channel_count here. */
1908 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001910 /* make sure the size is multiple of 32 bytes
1911 * At 48 kHz mono 16-bit PCM:
1912 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1913 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1914 */
1915 size += 0x1f;
1916 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001917
1918 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919}
1920
1921static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1922{
1923 struct stream_out *out = (struct stream_out *)stream;
1924
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001925 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926}
1927
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001928static int out_set_sample_rate(struct audio_stream *stream __unused,
1929 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930{
1931 return -ENOSYS;
1932}
1933
1934static size_t out_get_buffer_size(const struct audio_stream *stream)
1935{
1936 struct stream_out *out = (struct stream_out *)stream;
1937
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001938 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001940 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1941 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001943 return out->config.period_size *
1944 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945}
1946
1947static uint32_t out_get_channels(const struct audio_stream *stream)
1948{
1949 struct stream_out *out = (struct stream_out *)stream;
1950
1951 return out->channel_mask;
1952}
1953
1954static audio_format_t out_get_format(const struct audio_stream *stream)
1955{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001956 struct stream_out *out = (struct stream_out *)stream;
1957
1958 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959}
1960
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001961static int out_set_format(struct audio_stream *stream __unused,
1962 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963{
1964 return -ENOSYS;
1965}
1966
1967static int out_standby(struct audio_stream *stream)
1968{
1969 struct stream_out *out = (struct stream_out *)stream;
1970 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001971
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301972 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1973 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001974 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1975 /* Ignore standby in case of voip call because the voip output
1976 * stream is closed in adev_close_output_stream()
1977 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301978 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001979 return 0;
1980 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001982 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001984 if (adev->adm_deregister_stream)
1985 adev->adm_deregister_stream(adev->adm_data, out->handle);
1986
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001987 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001989 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 if (out->pcm) {
1991 pcm_close(out->pcm);
1992 out->pcm = NULL;
1993 }
1994 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001995 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301997 out->send_next_track_params = false;
1998 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001999 out->gapless_mdata.encoder_delay = 0;
2000 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002001 if (out->compr != NULL) {
2002 compress_close(out->compr);
2003 out->compr = NULL;
2004 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002007 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 }
2009 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302010 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 return 0;
2012}
2013
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002014static int out_dump(const struct audio_stream *stream __unused,
2015 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016{
2017 return 0;
2018}
2019
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002020static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2021{
2022 int ret = 0;
2023 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002024
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002025 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002026 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002027 return -EINVAL;
2028 }
2029
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302030 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002031
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002032 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2033 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302034 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002035 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002036 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2037 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302038 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002039 }
2040
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002041 ALOGV("%s new encoder delay %u and padding %u", __func__,
2042 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2043
2044 return 0;
2045}
2046
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002047static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2048{
2049 return out == adev->primary_output || out == adev->voice_tx_output;
2050}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2053{
2054 struct stream_out *out = (struct stream_out *)stream;
2055 struct audio_device *adev = out->dev;
2056 struct str_parms *parms;
2057 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002058 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
sangwoobc677242013-08-08 16:53:43 +09002060 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002061 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302063 if (!parms)
2064 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002065 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2066 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002068 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002069 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002071 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302072 * When HDMI cable is unplugged/usb hs is disconnected the
2073 * music playback is paused and the policy manager sends routing=0
2074 * But the audioflingercontinues to write data until standby time
2075 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 * Avoid this by routing audio to speaker until standby.
2077 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302078 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2079 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002080 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002081 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2082 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083 }
2084
2085 /*
2086 * select_devices() call below switches all the usecases on the same
2087 * backend to the new device. Refer to check_usecases_codec_backend() in
2088 * the select_devices(). But how do we undo this?
2089 *
2090 * For example, music playback is active on headset (deep-buffer usecase)
2091 * and if we go to ringtones and select a ringtone, low-latency usecase
2092 * will be started on headset+speaker. As we can't enable headset+speaker
2093 * and headset devices at the same time, select_devices() switches the music
2094 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2095 * So when the ringtone playback is completed, how do we undo the same?
2096 *
2097 * We are relying on the out_set_parameters() call on deep-buffer output,
2098 * once the ringtone playback is ended.
2099 * NOTE: We should not check if the current devices are same as new devices.
2100 * Because select_devices() must be called to switch back the music
2101 * playback to headset.
2102 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002103 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002104 out->devices = val;
2105
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302106 if (!out->standby) {
2107 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2108 adev->perf_lock_opts,
2109 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002110 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302111 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2112 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002113
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002114 if (output_drives_call(adev, out)) {
2115 if(!voice_is_in_call(adev)) {
2116 if (adev->mode == AUDIO_MODE_IN_CALL) {
2117 adev->current_call_output = out;
2118 ret = voice_start_call(adev);
2119 }
2120 } else {
2121 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002122 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002123 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002124 }
2125 }
2126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002128 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002130
2131 if (out == adev->primary_output) {
2132 pthread_mutex_lock(&adev->lock);
2133 audio_extn_set_parameters(adev, parms);
2134 pthread_mutex_unlock(&adev->lock);
2135 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002136 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002137 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002138 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002139
2140 audio_extn_dts_create_state_notifier_node(out->usecase);
2141 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2142 popcount(out->channel_mask),
2143 out->playback_started);
2144
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002145 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002146 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302149error:
Eric Laurent994a6932013-07-17 11:51:42 -07002150 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 return ret;
2152}
2153
2154static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2155{
2156 struct stream_out *out = (struct stream_out *)stream;
2157 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002158 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 char value[256];
2160 struct str_parms *reply = str_parms_create();
2161 size_t i, j;
2162 int ret;
2163 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002164
2165 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002166 if (reply) {
2167 str_parms_destroy(reply);
2168 }
2169 if (query) {
2170 str_parms_destroy(query);
2171 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002172 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2173 return NULL;
2174 }
2175
Eric Laurent994a6932013-07-17 11:51:42 -07002176 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2178 if (ret >= 0) {
2179 value[0] = '\0';
2180 i = 0;
2181 while (out->supported_channel_masks[i] != 0) {
2182 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2183 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2184 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002185 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002187 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 first = false;
2189 break;
2190 }
2191 }
2192 i++;
2193 }
2194 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2195 str = str_parms_to_str(reply);
2196 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002197 voice_extn_out_get_parameters(out, query, reply);
2198 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002199 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002200 free(str);
2201 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002202 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002204
Alexy Joseph62142aa2015-11-16 15:10:34 -08002205
2206 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2207 if (ret >= 0) {
2208 value[0] = '\0';
2209 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2210 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302211 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002212 } else {
2213 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302214 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002215 }
2216 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002217 if (str)
2218 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002219 str = str_parms_to_str(reply);
2220 }
2221
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002222 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2223 if (ret >= 0) {
2224 value[0] = '\0';
2225 i = 0;
2226 first = true;
2227 while (out->supported_formats[i] != 0) {
2228 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2229 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2230 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002231 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002232 }
2233 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2234 first = false;
2235 break;
2236 }
2237 }
2238 i++;
2239 }
2240 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002241 if (str)
2242 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002243 str = str_parms_to_str(reply);
2244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 str_parms_destroy(query);
2246 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002247 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 return str;
2249}
2250
2251static uint32_t out_get_latency(const struct audio_stream_out *stream)
2252{
2253 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002254 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255
Alexy Josephaa54c872014-12-03 02:46:47 -08002256 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002257 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002258 } else {
2259 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002260 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002261 }
2262
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302263 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002264 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265}
2266
2267static int out_set_volume(struct audio_stream_out *stream, float left,
2268 float right)
2269{
Eric Laurenta9024de2013-04-04 09:19:12 -07002270 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002271 int volume[2];
2272
Eric Laurenta9024de2013-04-04 09:19:12 -07002273 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2274 /* only take left channel into account: the API is for stereo anyway */
2275 out->muted = (left == 0.0f);
2276 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002277 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002278 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2279 /*
2280 * Set mute or umute on HDMI passthrough stream.
2281 * Only take left channel into account.
2282 * Mute is 0 and unmute 1
2283 */
2284 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2285 } else {
2286 char mixer_ctl_name[128];
2287 struct audio_device *adev = out->dev;
2288 struct mixer_ctl *ctl;
2289 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002290 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002292 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2293 "Compress Playback %d Volume", pcm_device_id);
2294 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2295 if (!ctl) {
2296 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2297 __func__, mixer_ctl_name);
2298 return -EINVAL;
2299 }
2300 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2301 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2302 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2303 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002305 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002307 return -ENOSYS;
2308}
2309
2310static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2311 size_t bytes)
2312{
2313 struct stream_out *out = (struct stream_out *)stream;
2314 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302315 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002316 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002318 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302319
Naresh Tanniru80659832014-06-04 18:17:56 +05302320 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002321
Ashish Jainbbce4322016-02-16 13:25:27 +05302322 if (is_offload_usecase(out->usecase)) {
2323 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302324 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2325 pthread_mutex_unlock(&out->lock);
2326 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302327 } else {
2328 /* increase written size during SSR to avoid mismatch
2329 * with the written frames count in AF
2330 */
2331 out->written += bytes / (out->config.channels * sizeof(short));
2332 ALOGD(" %s: sound card is not active/SSR state", __func__);
2333 ret= -EIO;
2334 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302335 }
2336 }
2337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002339 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002340 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002341 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2342 ret = voice_extn_compress_voip_start_output_stream(out);
2343 else
2344 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002345 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002348 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349 goto exit;
2350 }
vivek mehta446c3962015-09-14 10:57:35 -07002351 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002352 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354
Ashish Jain81eb2a82015-05-13 10:52:34 +05302355 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002356 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302357 adev->is_channel_status_set = true;
2358 }
2359
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002360 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002361 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002362 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002363 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002364 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2365 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302366 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2367 ALOGD("copl(%p):send next track params in gapless", out);
2368 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2369 out->send_next_track_params = false;
2370 out->is_compr_metadata_avail = false;
2371 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002372 }
2373
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302375 if (ret < 0)
2376 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302377 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002378 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302379 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302381 } else if (-ENETRESET == ret) {
2382 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2383 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2384 pthread_mutex_unlock(&out->lock);
2385 out_standby(&out->stream.common);
2386 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302388 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002390 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 out->playback_started = 1;
2392 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002393
2394 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2395 popcount(out->channel_mask),
2396 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 }
2398 pthread_mutex_unlock(&out->lock);
2399 return ret;
2400 } else {
2401 if (out->pcm) {
2402 if (out->muted)
2403 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002404
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302405 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002406
2407 if (adev->adm_request_focus)
2408 adev->adm_request_focus(adev->adm_data, out->handle);
2409
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002410 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2411 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2412 else
2413 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002414
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302415 if (ret < 0)
2416 ret = -errno;
2417 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002418 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002419
2420 if (adev->adm_abandon_focus)
2421 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 }
2424
2425exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302426 /* ToDo: There may be a corner case when SSR happens back to back during
2427 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302428 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302429 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302430 }
2431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 pthread_mutex_unlock(&out->lock);
2433
2434 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002435 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002436 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302437 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302438 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302439 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302440 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302441 out->standby = true;
2442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302444 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302445 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 }
2447 return bytes;
2448}
2449
2450static int out_get_render_position(const struct audio_stream_out *stream,
2451 uint32_t *dsp_frames)
2452{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302454 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002455
2456 if (dsp_frames == NULL)
2457 return -EINVAL;
2458
2459 *dsp_frames = 0;
2460 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002461 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002462 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302464 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002465 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302466 if (ret < 0)
2467 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 ALOGVV("%s rendered frames %d sample_rate %d",
2469 __func__, *dsp_frames, out->sample_rate);
2470 }
2471 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302472 if (-ENETRESET == ret) {
2473 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2474 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2475 return -EINVAL;
2476 } else if(ret < 0) {
2477 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2478 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302479 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2480 /*
2481 * Handle corner case where compress session is closed during SSR
2482 * and timestamp is queried
2483 */
2484 ALOGE(" ERROR: sound card not active, return error");
2485 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302486 } else {
2487 return 0;
2488 }
Zhou Song32a556e2015-05-05 10:46:56 +08002489 } else if (audio_is_linear_pcm(out->format)) {
2490 *dsp_frames = out->written;
2491 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002492 } else
2493 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494}
2495
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002496static int out_add_audio_effect(const struct audio_stream *stream __unused,
2497 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498{
2499 return 0;
2500}
2501
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002502static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2503 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504{
2505 return 0;
2506}
2507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002508static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2509 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510{
2511 return -EINVAL;
2512}
2513
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002514static int out_get_presentation_position(const struct audio_stream_out *stream,
2515 uint64_t *frames, struct timespec *timestamp)
2516{
2517 struct stream_out *out = (struct stream_out *)stream;
2518 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002519 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002520
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002521 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002522
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002523 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002524 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302525 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002526 &out->sample_rate);
2527 ALOGVV("%s rendered frames %ld sample_rate %d",
2528 __func__, dsp_frames, out->sample_rate);
2529 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302530 if (ret < 0)
2531 ret = -errno;
2532 if (-ENETRESET == ret) {
2533 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2534 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2535 ret = -EINVAL;
2536 } else
2537 ret = 0;
2538
Eric Laurent949a0892013-09-20 09:20:13 -07002539 /* this is the best we can do */
2540 clock_gettime(CLOCK_MONOTONIC, timestamp);
2541 }
2542 } else {
2543 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002544 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002545 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2546 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002547 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002548 // This adjustment accounts for buffering after app processor.
2549 // It is based on estimated DSP latency per use case, rather than exact.
2550 signed_frames -=
2551 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2552
Eric Laurent949a0892013-09-20 09:20:13 -07002553 // It would be unusual for this value to be negative, but check just in case ...
2554 if (signed_frames >= 0) {
2555 *frames = signed_frames;
2556 ret = 0;
2557 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002558 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302559 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2560 *frames = out->written;
2561 clock_gettime(CLOCK_MONOTONIC, timestamp);
2562 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002563 }
2564 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002565 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002566 return ret;
2567}
2568
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002569static int out_set_callback(struct audio_stream_out *stream,
2570 stream_callback_t callback, void *cookie)
2571{
2572 struct stream_out *out = (struct stream_out *)stream;
2573
2574 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002575 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 out->offload_callback = callback;
2577 out->offload_cookie = cookie;
2578 pthread_mutex_unlock(&out->lock);
2579 return 0;
2580}
2581
2582static int out_pause(struct audio_stream_out* stream)
2583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585 int status = -ENOSYS;
2586 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002587 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002588 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002589 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002590 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302591 struct audio_device *adev = out->dev;
2592 int snd_scard_state = get_snd_card_state(adev);
2593
2594 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2595 status = compress_pause(out->compr);
2596
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002597 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002598
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302599 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002600 audio_extn_dts_notify_playback_state(out->usecase, 0,
2601 out->sample_rate, popcount(out->channel_mask),
2602 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002603 }
2604 pthread_mutex_unlock(&out->lock);
2605 }
2606 return status;
2607}
2608
2609static int out_resume(struct audio_stream_out* stream)
2610{
2611 struct stream_out *out = (struct stream_out *)stream;
2612 int status = -ENOSYS;
2613 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002614 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002615 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002617 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302619 struct audio_device *adev = out->dev;
2620 int snd_scard_state = get_snd_card_state(adev);
2621
2622 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2623 status = compress_resume(out->compr);
2624
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002626
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302627 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002628 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2629 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002630 }
2631 pthread_mutex_unlock(&out->lock);
2632 }
2633 return status;
2634}
2635
2636static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2637{
2638 struct stream_out *out = (struct stream_out *)stream;
2639 int status = -ENOSYS;
2640 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002641 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002642 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002643 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2644 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2645 else
2646 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2647 pthread_mutex_unlock(&out->lock);
2648 }
2649 return status;
2650}
2651
2652static int out_flush(struct audio_stream_out* stream)
2653{
2654 struct stream_out *out = (struct stream_out *)stream;
2655 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002656 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002657 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002658 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 stop_compressed_output_l(out);
2660 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002661 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662 return 0;
2663 }
2664 return -ENOSYS;
2665}
2666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667/** audio_stream_in implementation **/
2668static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2669{
2670 struct stream_in *in = (struct stream_in *)stream;
2671
2672 return in->config.rate;
2673}
2674
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002675static int in_set_sample_rate(struct audio_stream *stream __unused,
2676 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677{
2678 return -ENOSYS;
2679}
2680
2681static size_t in_get_buffer_size(const struct audio_stream *stream)
2682{
2683 struct stream_in *in = (struct stream_in *)stream;
2684
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002685 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2686 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002687 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2688 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002689
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002690 return in->config.period_size *
2691 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692}
2693
2694static uint32_t in_get_channels(const struct audio_stream *stream)
2695{
2696 struct stream_in *in = (struct stream_in *)stream;
2697
2698 return in->channel_mask;
2699}
2700
2701static audio_format_t in_get_format(const struct audio_stream *stream)
2702{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002703 struct stream_in *in = (struct stream_in *)stream;
2704
2705 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706}
2707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002708static int in_set_format(struct audio_stream *stream __unused,
2709 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710{
2711 return -ENOSYS;
2712}
2713
2714static int in_standby(struct audio_stream *stream)
2715{
2716 struct stream_in *in = (struct stream_in *)stream;
2717 struct audio_device *adev = in->dev;
2718 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302719 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2720 stream, in->usecase, use_case_table[in->usecase]);
2721
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002722 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2723 /* Ignore standby in case of voip call because the voip input
2724 * stream is closed in adev_close_input_stream()
2725 */
2726 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2727 return status;
2728 }
2729
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002730 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002731 if (!in->standby && in->is_st_session) {
2732 ALOGD("%s: sound trigger pcm stop lab", __func__);
2733 audio_extn_sound_trigger_stop_lab(in);
2734 in->standby = 1;
2735 }
2736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002738 if (adev->adm_deregister_stream)
2739 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2740
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002741 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002743 if (in->pcm) {
2744 pcm_close(in->pcm);
2745 in->pcm = NULL;
2746 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002748 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 }
2750 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002751 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 return status;
2753}
2754
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002755static int in_dump(const struct audio_stream *stream __unused,
2756 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757{
2758 return 0;
2759}
2760
2761static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2762{
2763 struct stream_in *in = (struct stream_in *)stream;
2764 struct audio_device *adev = in->dev;
2765 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002767 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302769 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 parms = str_parms_create_str(kvpairs);
2771
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302772 if (!parms)
2773 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002774 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002775 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002776
2777 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2778 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 val = atoi(value);
2780 /* no audio source uses val == 0 */
2781 if ((in->source != val) && (val != 0)) {
2782 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002783 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2784 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2785 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08002786 (in->config.rate == 8000 || in->config.rate == 16000 ||
2787 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002788 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002789 err = voice_extn_compress_voip_open_input_stream(in);
2790 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002791 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002792 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002793 }
2794 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 }
2796 }
2797
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002798 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2799 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002801 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 in->device = val;
2803 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002804 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002805 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 }
2807 }
2808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002810 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811
2812 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302813error:
Eric Laurent994a6932013-07-17 11:51:42 -07002814 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 return ret;
2816}
2817
2818static char* in_get_parameters(const struct audio_stream *stream,
2819 const char *keys)
2820{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002821 struct stream_in *in = (struct stream_in *)stream;
2822 struct str_parms *query = str_parms_create_str(keys);
2823 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002824 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;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302860 int 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;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303007 int 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) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303228 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003229 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;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003419 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003420 int ret;
3421 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003422
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003423 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303426 if (!parms)
3427 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003428 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3429 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303430 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303431 if (strstr(snd_card_status, "OFFLINE")) {
3432 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303433 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003434 //close compress sessions on OFFLINE status
3435 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303436 } else if (strstr(snd_card_status, "ONLINE")) {
3437 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303438 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003439 //send dts hpx license if enabled
3440 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303441 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303442 }
3443
3444 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003445 status = voice_set_parameters(adev, parms);
3446 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003447 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003449 status = platform_set_parameters(adev->platform, parms);
3450 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003451 goto done;
3452
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003453 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3454 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003455 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3457 adev->bluetooth_nrec = true;
3458 else
3459 adev->bluetooth_nrec = false;
3460 }
3461
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003462 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3463 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3465 adev->screen_off = false;
3466 else
3467 adev->screen_off = true;
3468 }
3469
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003470 ret = str_parms_get_int(parms, "rotation", &val);
3471 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003472 bool reverse_speakers = false;
3473 switch(val) {
3474 // FIXME: note that the code below assumes that the speakers are in the correct placement
3475 // relative to the user when the device is rotated 90deg from its default rotation. This
3476 // assumption is device-specific, not platform-specific like this code.
3477 case 270:
3478 reverse_speakers = true;
3479 break;
3480 case 0:
3481 case 90:
3482 case 180:
3483 break;
3484 default:
3485 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003486 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003487 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003488 if (status == 0) {
3489 if (adev->speaker_lr_swap != reverse_speakers) {
3490 adev->speaker_lr_swap = reverse_speakers;
3491 // only update the selected device if there is active pcm playback
3492 struct audio_usecase *usecase;
3493 struct listnode *node;
3494 list_for_each(node, &adev->usecase_list) {
3495 usecase = node_to_item(node, struct audio_usecase, list);
3496 if (usecase->type == PCM_PLAYBACK) {
3497 select_devices(adev, usecase->id);
3498 break;
3499 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003500 }
3501 }
3502 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003503 }
3504
Mingming Yin514a8bc2014-07-29 15:22:21 -07003505 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3506 if (ret >= 0) {
3507 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3508 adev->bt_wb_speech_enabled = true;
3509 else
3510 adev->bt_wb_speech_enabled = false;
3511 }
3512
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003513 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3514 if (ret >= 0) {
3515 val = atoi(value);
3516 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3517 ALOGV("cache new edid");
3518 platform_cache_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003519 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3520 /*
3521 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
3522 * Per AudioPolicyManager, USB device is higher priority than WFD.
3523 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
3524 * If WFD use case occupies AFE proxy, it may result unintended behavior while
3525 * starting voice call on USB
3526 */
3527 ALOGV("detected USB connect .. disable proxy");
3528 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003529 }
3530 }
3531
3532 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3533 if (ret >= 0) {
3534 val = atoi(value);
3535 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3536 ALOGV("invalidate cached edid");
3537 platform_invalidate_edid(adev->platform);
vivek mehta344576a2016-04-12 18:56:03 -07003538 } else if (val & AUDIO_DEVICE_OUT_USB_DEVICE) {
3539 ALOGV("detected USB disconnect .. enable proxy");
3540 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003541 }
3542 }
3543
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003544 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003545
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003546done:
3547 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003548 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303549error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003550 ALOGV("%s: exit with code(%d)", __func__, status);
3551 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552}
3553
3554static char* adev_get_parameters(const struct audio_hw_device *dev,
3555 const char *keys)
3556{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003557 struct audio_device *adev = (struct audio_device *)dev;
3558 struct str_parms *reply = str_parms_create();
3559 struct str_parms *query = str_parms_create_str(keys);
3560 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303561 char value[256] = {0};
3562 int ret = 0;
3563
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003564 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003565 if (reply) {
3566 str_parms_destroy(reply);
3567 }
3568 if (query) {
3569 str_parms_destroy(query);
3570 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003571 ALOGE("adev_get_parameters: failed to create query or reply");
3572 return NULL;
3573 }
3574
Naresh Tannirud7205b62014-06-20 02:54:48 +05303575 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3576 sizeof(value));
3577 if (ret >=0) {
3578 int val = 1;
3579 pthread_mutex_lock(&adev->snd_card_status.lock);
3580 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3581 val = 0;
3582 pthread_mutex_unlock(&adev->snd_card_status.lock);
3583 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3584 goto exit;
3585 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003586
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003587 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003588 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003589 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003590 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303591 pthread_mutex_unlock(&adev->lock);
3592
Naresh Tannirud7205b62014-06-20 02:54:48 +05303593exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003594 str = str_parms_to_str(reply);
3595 str_parms_destroy(query);
3596 str_parms_destroy(reply);
3597
3598 ALOGV("%s: exit: returns - %s", __func__, str);
3599 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600}
3601
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003602static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603{
3604 return 0;
3605}
3606
3607static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3608{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003609 int ret;
3610 struct audio_device *adev = (struct audio_device *)dev;
3611 pthread_mutex_lock(&adev->lock);
3612 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003613 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003614 pthread_mutex_unlock(&adev->lock);
3615 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616}
3617
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003618static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3619 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620{
3621 return -ENOSYS;
3622}
3623
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003624static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3625 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626{
3627 return -ENOSYS;
3628}
3629
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003630static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3631 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632{
3633 return -ENOSYS;
3634}
3635
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003636static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3637 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638{
3639 return -ENOSYS;
3640}
3641
3642static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3643{
3644 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 pthread_mutex_lock(&adev->lock);
3647 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003648 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003650 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003651 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003652 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003653 adev->current_call_output = NULL;
3654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 }
3656 pthread_mutex_unlock(&adev->lock);
3657 return 0;
3658}
3659
3660static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3661{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003662 int ret;
3663
3664 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003665 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003666 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3667 pthread_mutex_unlock(&adev->lock);
3668
3669 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670}
3671
3672static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3673{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003674 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 return 0;
3676}
3677
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003678static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 const struct audio_config *config)
3680{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003681 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003683 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3684 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685}
3686
3687static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003688 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 audio_devices_t devices,
3690 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003691 struct audio_stream_in **stream_in,
3692 audio_input_flags_t flags __unused,
3693 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003694 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695{
3696 struct audio_device *adev = (struct audio_device *)dev;
3697 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003698 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003699 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003700 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 *stream_in = NULL;
3703 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3704 return -EINVAL;
3705
3706 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003707
3708 if (!in) {
3709 ALOGE("failed to allocate input stream");
3710 return -ENOMEM;
3711 }
3712
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303713 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003714 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3715 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003717 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003718 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 in->stream.common.get_sample_rate = in_get_sample_rate;
3721 in->stream.common.set_sample_rate = in_set_sample_rate;
3722 in->stream.common.get_buffer_size = in_get_buffer_size;
3723 in->stream.common.get_channels = in_get_channels;
3724 in->stream.common.get_format = in_get_format;
3725 in->stream.common.set_format = in_set_format;
3726 in->stream.common.standby = in_standby;
3727 in->stream.common.dump = in_dump;
3728 in->stream.common.set_parameters = in_set_parameters;
3729 in->stream.common.get_parameters = in_get_parameters;
3730 in->stream.common.add_audio_effect = in_add_audio_effect;
3731 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3732 in->stream.set_gain = in_set_gain;
3733 in->stream.read = in_read;
3734 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3735
3736 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003737 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 in->standby = 1;
3740 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003741 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003742 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743
3744 /* Update config params with the requested sample rate and channels */
3745 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003746 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3747 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3748 is_low_latency = true;
3749#if LOW_LATENCY_CAPTURE_USE_CASE
3750 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3751#endif
3752 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003755 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003757 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303758 if (adev->mode != AUDIO_MODE_IN_CALL) {
3759 ret = -EINVAL;
3760 goto err_open;
3761 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003762 if (config->sample_rate == 0)
3763 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3764 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3765 config->sample_rate != 8000) {
3766 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3767 ret = -EINVAL;
3768 goto err_open;
3769 }
3770 if (config->format == AUDIO_FORMAT_DEFAULT)
3771 config->format = AUDIO_FORMAT_PCM_16_BIT;
3772 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3773 config->format = AUDIO_FORMAT_PCM_16_BIT;
3774 ret = -EINVAL;
3775 goto err_open;
3776 }
3777
3778 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3779 in->config = pcm_config_afe_proxy_record;
3780 in->config.channels = channel_count;
3781 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303782 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3783 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003784 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003785 audio_extn_compr_cap_format_supported(config->format) &&
3786 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003787 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003788 } else {
3789 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003790 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003791 buffer_size = get_input_buffer_size(config->sample_rate,
3792 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003793 channel_count,
3794 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003795 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003796 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3797 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3798 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003799 (in->config.rate == 8000 || in->config.rate == 16000 ||
3800 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003801 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3802 voice_extn_compress_voip_open_input_stream(in);
3803 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003804 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003806 /* This stream could be for sound trigger lab,
3807 get sound trigger pcm if present */
3808 audio_extn_sound_trigger_check_and_get_session(in);
3809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003811 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003812 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813
3814err_open:
3815 free(in);
3816 *stream_in = NULL;
3817 return ret;
3818}
3819
3820static void adev_close_input_stream(struct audio_hw_device *dev,
3821 struct audio_stream_in *stream)
3822{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003823 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003824 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003825 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303826
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303827 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003828
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303829 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003830 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303831
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003832 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303833 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003834 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303835 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003836 if (ret != 0)
3837 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3838 __func__, ret);
3839 } else
3840 in_standby(&stream->common);
3841
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003842 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003843 audio_extn_ssr_deinit();
3844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845
Mingming Yine62d7842013-10-25 16:26:03 -07003846 if(audio_extn_compr_cap_enabled() &&
3847 audio_extn_compr_cap_format_supported(in->config.format))
3848 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003849
Mingming Yinfd7607b2016-01-22 12:48:44 -08003850 if (in->is_st_session) {
3851 ALOGV("%s: sound trigger pcm stop lab", __func__);
3852 audio_extn_sound_trigger_stop_lab(in);
3853 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003854 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 return;
3856}
3857
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003858static int adev_dump(const audio_hw_device_t *device __unused,
3859 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860{
3861 return 0;
3862}
3863
3864static int adev_close(hw_device_t *device)
3865{
3866 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003867
3868 if (!adev)
3869 return 0;
3870
3871 pthread_mutex_lock(&adev_init_lock);
3872
3873 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003874 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003875 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003876 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003877 audio_route_free(adev->audio_route);
3878 free(adev->snd_dev_ref_cnt);
3879 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003880 if (adev->adm_deinit)
3881 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003882 free(device);
3883 adev = NULL;
3884 }
3885 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 return 0;
3888}
3889
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003890/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3891 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3892 * just that it _might_ work.
3893 */
3894static int period_size_is_plausible_for_low_latency(int period_size)
3895{
3896 switch (period_size) {
3897 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003898 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003899 case 240:
3900 case 320:
3901 case 480:
3902 return 1;
3903 default:
3904 return 0;
3905 }
3906}
3907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908static int adev_open(const hw_module_t *module, const char *name,
3909 hw_device_t **device)
3910{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003911 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3913
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003914 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003915 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003916 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003917 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003918 ALOGD("%s: returning existing instance of adev", __func__);
3919 ALOGD("%s: exit", __func__);
3920 pthread_mutex_unlock(&adev_init_lock);
3921 return 0;
3922 }
3923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924 adev = calloc(1, sizeof(struct audio_device));
3925
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003926 if (!adev) {
3927 pthread_mutex_unlock(&adev_init_lock);
3928 return -ENOMEM;
3929 }
3930
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003931 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3934 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3935 adev->device.common.module = (struct hw_module_t *)module;
3936 adev->device.common.close = adev_close;
3937
3938 adev->device.init_check = adev_init_check;
3939 adev->device.set_voice_volume = adev_set_voice_volume;
3940 adev->device.set_master_volume = adev_set_master_volume;
3941 adev->device.get_master_volume = adev_get_master_volume;
3942 adev->device.set_master_mute = adev_set_master_mute;
3943 adev->device.get_master_mute = adev_get_master_mute;
3944 adev->device.set_mode = adev_set_mode;
3945 adev->device.set_mic_mute = adev_set_mic_mute;
3946 adev->device.get_mic_mute = adev_get_mic_mute;
3947 adev->device.set_parameters = adev_set_parameters;
3948 adev->device.get_parameters = adev_get_parameters;
3949 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3950 adev->device.open_output_stream = adev_open_output_stream;
3951 adev->device.close_output_stream = adev_close_output_stream;
3952 adev->device.open_input_stream = adev_open_input_stream;
3953 adev->device.close_input_stream = adev_close_input_stream;
3954 adev->device.dump = adev_dump;
3955
3956 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003958 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003959 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003962 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07003963 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003964 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003965 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003966 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003967 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003968 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003969 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303970 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303971 adev->perf_lock_opts[0] = 0x101;
3972 adev->perf_lock_opts[1] = 0x20E;
3973 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303974
3975 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3976 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003978 adev->platform = platform_init(adev);
3979 if (!adev->platform) {
3980 free(adev->snd_dev_ref_cnt);
3981 free(adev);
3982 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3983 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003984 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003985 return -EINVAL;
3986 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003987
Naresh Tanniru4c630392014-05-12 01:05:52 +05303988 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3989
Eric Laurentc4aef752013-09-12 17:45:53 -07003990 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3991 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3992 if (adev->visualizer_lib == NULL) {
3993 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3994 } else {
3995 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3996 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003997 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003998 "visualizer_hal_start_output");
3999 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004000 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004001 "visualizer_hal_stop_output");
4002 }
4003 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004004 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004005 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004006
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004007 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4008 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4009 if (adev->offload_effects_lib == NULL) {
4010 ALOGE("%s: DLOPEN failed for %s", __func__,
4011 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4012 } else {
4013 ALOGV("%s: DLOPEN successful for %s", __func__,
4014 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4015 adev->offload_effects_start_output =
4016 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4017 "offload_effects_bundle_hal_start_output");
4018 adev->offload_effects_stop_output =
4019 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4020 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004021 adev->offload_effects_set_hpx_state =
4022 (int (*)(bool))dlsym(adev->offload_effects_lib,
4023 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304024 adev->offload_effects_get_parameters =
4025 (void (*)(struct str_parms *, struct str_parms *))
4026 dlsym(adev->offload_effects_lib,
4027 "offload_effects_bundle_get_parameters");
4028 adev->offload_effects_set_parameters =
4029 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4030 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004031 }
4032 }
4033
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004034 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4035 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4036 if (adev->adm_lib == NULL) {
4037 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4038 } else {
4039 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4040 adev->adm_init = (adm_init_t)
4041 dlsym(adev->adm_lib, "adm_init");
4042 adev->adm_deinit = (adm_deinit_t)
4043 dlsym(adev->adm_lib, "adm_deinit");
4044 adev->adm_register_input_stream = (adm_register_input_stream_t)
4045 dlsym(adev->adm_lib, "adm_register_input_stream");
4046 adev->adm_register_output_stream = (adm_register_output_stream_t)
4047 dlsym(adev->adm_lib, "adm_register_output_stream");
4048 adev->adm_deregister_stream = (adm_deregister_stream_t)
4049 dlsym(adev->adm_lib, "adm_deregister_stream");
4050 adev->adm_request_focus = (adm_request_focus_t)
4051 dlsym(adev->adm_lib, "adm_request_focus");
4052 adev->adm_abandon_focus = (adm_abandon_focus_t)
4053 dlsym(adev->adm_lib, "adm_abandon_focus");
4054 }
4055 }
4056
Mingming Yin514a8bc2014-07-29 15:22:21 -07004057 adev->bt_wb_speech_enabled = false;
4058
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004059 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 *device = &adev->device.common;
4061
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004062 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4063 &adev->streams_output_cfg_list);
4064
Kiran Kandi910e1862013-10-29 13:29:42 -07004065 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004066
4067 char value[PROPERTY_VALUE_MAX];
4068 int trial;
4069 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4070 trial = atoi(value);
4071 if (period_size_is_plausible_for_low_latency(trial)) {
4072 pcm_config_low_latency.period_size = trial;
4073 pcm_config_low_latency.start_threshold = trial / 4;
4074 pcm_config_low_latency.avail_min = trial / 4;
4075 configured_low_latency_capture_period_size = trial;
4076 }
4077 }
4078 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4079 trial = atoi(value);
4080 if (period_size_is_plausible_for_low_latency(trial)) {
4081 configured_low_latency_capture_period_size = trial;
4082 }
4083 }
4084
vivek mehta446c3962015-09-14 10:57:35 -07004085 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004086 pthread_mutex_unlock(&adev_init_lock);
4087
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004088 if (adev->adm_init)
4089 adev->adm_data = adev->adm_init();
4090
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304091 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004092 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093 return 0;
4094}
4095
4096static struct hw_module_methods_t hal_module_methods = {
4097 .open = adev_open,
4098};
4099
4100struct audio_module HAL_MODULE_INFO_SYM = {
4101 .common = {
4102 .tag = HARDWARE_MODULE_TAG,
4103 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4104 .hal_api_version = HARDWARE_HAL_API_VERSION,
4105 .id = AUDIO_HARDWARE_MODULE_ID,
4106 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004107 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 .methods = &hal_module_methods,
4109 },
4110};