blob: 35522ac692a0a98e0616e98e31e784a85216397b [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700168 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
169 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700170 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700171 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700172 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
179 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700180
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700182 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700184 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700185 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800186 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800187 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700188 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700189
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE2_CALL] = "voice2-call",
191 [USECASE_VOLTE_CALL] = "volte-call",
192 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800193 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800194 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
195 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800196 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700197 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
198 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800200 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
201 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
202 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
203
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700204 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
205 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700206 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
207 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700208
209 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
210 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700213static const audio_usecase_t offload_usecases[] = {
214 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800224
225#define STRING_TO_ENUM(string) { #string, string }
226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800227struct string_to_enum {
228 const char *name;
229 uint32_t value;
230};
231
232static const struct string_to_enum out_channels_name_to_enum_table[] = {
233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
240};
241
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700242static const struct string_to_enum out_formats_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
246};
247
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700248static struct audio_device *adev = NULL;
249static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700250static unsigned int audio_device_ref_count;
251
Haynes Mathew George5191a852013-09-11 14:19:36 -0700252static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253
vivek mehtaa76401a2015-04-24 14:12:15 -0700254__attribute__ ((visibility ("default")))
255bool audio_hw_send_gain_dep_calibration(int level) {
256 bool ret_val = false;
257 ALOGV("%s: called ... ", __func__);
258
259 pthread_mutex_lock(&adev_init_lock);
260
261 if (adev != NULL && adev->platform != NULL) {
262 pthread_mutex_lock(&adev->lock);
263 ret_val = platform_send_gain_dep_cal(adev->platform, level);
264 pthread_mutex_unlock(&adev->lock);
265 } else {
266 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
267 }
268
269 pthread_mutex_unlock(&adev_init_lock);
270
271 return ret_val;
272}
273
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800274static int check_and_set_gapless_mode(struct audio_device *adev) {
275
276
277 char value[PROPERTY_VALUE_MAX] = {0};
278 bool gapless_enabled = false;
279 const char *mixer_ctl_name = "Compress Gapless Playback";
280 struct mixer_ctl *ctl;
281
282 ALOGV("%s:", __func__);
283 property_get("audio.offload.gapless.enabled", value, NULL);
284 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
285
286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
287 if (!ctl) {
288 ALOGE("%s: Could not get ctl for mixer cmd - %s",
289 __func__, mixer_ctl_name);
290 return -EINVAL;
291 }
292
293 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
294 ALOGE("%s: Could not set gapless mode %d",
295 __func__, gapless_enabled);
296 return -EINVAL;
297 }
298 return 0;
299}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700300
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301static bool is_supported_format(audio_format_t format)
302{
Eric Laurent86e17132013-09-12 17:49:30 -0700303 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530304 format == AUDIO_FORMAT_AAC_LC ||
305 format == AUDIO_FORMAT_AAC_HE_V1 ||
306 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530307 format == AUDIO_FORMAT_AAC_ADTS_LC ||
308 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
309 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700311 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700312 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800313 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530314 format == AUDIO_FORMAT_ALAC ||
315 format == AUDIO_FORMAT_APE ||
316 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800317 format == AUDIO_FORMAT_WMA ||
318 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800319 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700320
321 return false;
322}
323
324static int get_snd_codec_id(audio_format_t format)
325{
326 int id = 0;
327
Ashish Jainf9b78162014-08-25 20:36:25 +0530328 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700329 case AUDIO_FORMAT_MP3:
330 id = SND_AUDIOCODEC_MP3;
331 break;
332 case AUDIO_FORMAT_AAC:
333 id = SND_AUDIOCODEC_AAC;
334 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530335 case AUDIO_FORMAT_AAC_ADTS:
336 id = SND_AUDIOCODEC_AAC;
337 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530338 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehta0ea887a2015-08-26 14:01:20 -0700339 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800340 id = SND_AUDIOCODEC_PCM;
341 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700342 case AUDIO_FORMAT_FLAC:
343 id = SND_AUDIOCODEC_FLAC;
344 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530345 case AUDIO_FORMAT_ALAC:
346 id = SND_AUDIOCODEC_ALAC;
347 break;
348 case AUDIO_FORMAT_APE:
349 id = SND_AUDIOCODEC_APE;
350 break;
351 case AUDIO_FORMAT_VORBIS:
352 id = SND_AUDIOCODEC_VORBIS;
353 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800354 case AUDIO_FORMAT_WMA:
355 id = SND_AUDIOCODEC_WMA;
356 break;
357 case AUDIO_FORMAT_WMA_PRO:
358 id = SND_AUDIOCODEC_WMA_PRO;
359 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700360 default:
Mingming Yin90310102013-11-13 16:57:00 -0800361 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700362 }
363
364 return id;
365}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800366
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530367int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530368{
369 int snd_scard_state;
370
371 if (!adev)
372 return SND_CARD_STATE_OFFLINE;
373
374 pthread_mutex_lock(&adev->snd_card_status.lock);
375 snd_scard_state = adev->snd_card_status.state;
376 pthread_mutex_unlock(&adev->snd_card_status.lock);
377
378 return snd_scard_state;
379}
380
381static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
382{
383 if (!adev)
384 return -ENOSYS;
385
386 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700387 if (adev->snd_card_status.state != snd_scard_state) {
388 adev->snd_card_status.state = snd_scard_state;
389 platform_snd_card_update(adev->platform, snd_scard_state);
390 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530391 pthread_mutex_unlock(&adev->snd_card_status.lock);
392
393 return 0;
394}
395
Avinash Vaish71a8b972014-07-24 15:36:33 +0530396static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
397 struct audio_usecase *uc_info)
398{
399 struct listnode *node;
400 struct audio_usecase *usecase;
401
402 if (uc_info == NULL)
403 return -EINVAL;
404
405 /* Re-route all voice usecases on the shared backend other than the
406 specified usecase to new snd devices */
407 list_for_each(node, &adev->usecase_list) {
408 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800409 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530410 enable_audio_route(adev, usecase);
411 }
412 return 0;
413}
414
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700415int pcm_ioctl(struct pcm *pcm, int request, ...)
416{
417 va_list ap;
418 void * arg;
419 int pcm_fd = *(int*)pcm;
420
421 va_start(ap, request);
422 arg = va_arg(ap, void *);
423 va_end(ap);
424
425 return ioctl(pcm_fd, request, arg);
426}
427
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700428int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700429 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800430{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700431 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700432 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433
434 if (usecase == NULL)
435 return -EINVAL;
436
437 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
438
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800439 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700440 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800441 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700442 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800443
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800444#ifdef DS1_DOLBY_DAP_ENABLED
445 audio_extn_dolby_set_dmid(adev);
446 audio_extn_dolby_set_endpoint(adev);
447#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700448 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700451 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530452 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800453 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700454 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700455 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700456 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457 ALOGV("%s: exit", __func__);
458 return 0;
459}
460
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700461int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700462 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700464 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700465 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800466
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530467 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800468 return -EINVAL;
469
470 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700471 if (usecase->type == PCM_CAPTURE)
472 snd_device = usecase->in_snd_device;
473 else
474 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800475 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700476 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700477 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700478 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530480 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481 ALOGV("%s: exit", __func__);
482 return 0;
483}
484
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700485int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700486 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700488 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
489
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800490 if (snd_device < SND_DEVICE_MIN ||
491 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800492 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800493 return -EINVAL;
494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700495
496 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700497
498 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
499 ALOGE("%s: Invalid sound device returned", __func__);
500 return -EINVAL;
501 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700502 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700503 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700504 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 return 0;
506 }
507
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530508
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700509 if (audio_extn_spkr_prot_is_enabled())
510 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511 /* start usb playback thread */
512 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
513 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
514 audio_extn_usb_start_playback(adev);
515
516 /* start usb capture thread */
517 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
518 audio_extn_usb_start_capture(adev);
519
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800520 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
521 audio_extn_spkr_prot_is_enabled()) {
522 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 adev->snd_dev_ref_cnt[snd_device]--;
524 return -EINVAL;
525 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200526 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800527 if (audio_extn_spkr_prot_start_processing(snd_device)) {
528 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200529 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800530 return -EINVAL;
531 }
532 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700533 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700534 /* due to the possibility of calibration overwrite between listen
535 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700536 audio_extn_sound_trigger_update_device_status(snd_device,
537 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530538 audio_extn_listen_update_device_status(snd_device,
539 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700540 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700542 audio_extn_sound_trigger_update_device_status(snd_device,
543 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530544 audio_extn_listen_update_device_status(snd_device,
545 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700546 return -EINVAL;
547 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300548 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700549 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530550
551 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
552 !adev->native_playback_enabled &&
553 audio_is_true_native_stream_active(adev)) {
554 ALOGD("%s: %d: napb: enabling native mode in hardware",
555 __func__, __LINE__);
556 audio_route_apply_and_update_path(adev->audio_route,
557 "true-native-mode");
558 adev->native_playback_enabled = true;
559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 return 0;
562}
563
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700564int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700565 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800566{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700567 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
568
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 if (snd_device < SND_DEVICE_MIN ||
570 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800571 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800572 return -EINVAL;
573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
575 ALOGE("%s: device ref cnt is already 0", __func__);
576 return -EINVAL;
577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700580
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700581 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
582 ALOGE("%s: Invalid sound device returned", __func__);
583 return -EINVAL;
584 }
585
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700587 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800588 /* exit usb play back thread */
589 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
590 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
591 audio_extn_usb_stop_playback();
592
593 /* exit usb capture thread */
594 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700595 audio_extn_usb_stop_capture();
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800596
597 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
598 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700599 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300600 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700601 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300602 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700603
Ashish Jain81eb2a82015-05-13 10:52:34 +0530604 if (snd_device == SND_DEVICE_OUT_HDMI)
605 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530606 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
607 adev->native_playback_enabled) {
608 ALOGD("%s: %d: napb: disabling native mode in hardware",
609 __func__, __LINE__);
610 audio_route_reset_and_update_path(adev->audio_route,
611 "true-native-mode");
612 adev->native_playback_enabled = false;
613 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530614
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200615 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700616 audio_extn_sound_trigger_update_device_status(snd_device,
617 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530618 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800619 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800622 return 0;
623}
624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625static void check_usecases_codec_backend(struct audio_device *adev,
626 struct audio_usecase *uc_info,
627 snd_device_t snd_device)
628{
629 struct listnode *node;
630 struct audio_usecase *usecase;
631 bool switch_device[AUDIO_USECASE_MAX];
632 int i, num_uc_to_switch = 0;
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800633 int backend_idx = DEFAULT_CODEC_BACKEND;
634 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635
636 /*
637 * This function is to make sure that all the usecases that are active on
638 * the hardware codec backend are always routed to any one device that is
639 * handled by the hardware codec.
640 * For example, if low-latency and deep-buffer usecases are currently active
641 * on speaker and out_set_parameters(headset) is received on low-latency
642 * output, then we have to make sure deep-buffer is also switched to headset,
643 * because of the limitation that both the devices cannot be enabled
644 * at the same time as they share the same backend.
645 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700646 /*
647 * This call is to check if we need to force routing for a particular stream
648 * If there is a backend configuration change for the device when a
649 * new stream starts, then ADM needs to be closed and re-opened with the new
650 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800651 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700652 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800653 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
654 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530655
656 ALOGD("%s:becf: force routing %d", __func__, force_routing);
657
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800658 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800660 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800661 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 for (i = 0; i < AUDIO_USECASE_MAX; i++)
663 switch_device[i] = false;
664
665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800667
668 if (usecase == uc_info)
669 continue;
670 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530671
672 ALOGD("%s:becf: (%d) check_usecases backend_idx: %d,"
673 "usecase_backend_idx: %d, curr device: %s, usecase device:%s",
674 __func__, i, backend_idx, usecase_backend_idx,
675 platform_get_snd_device_name(snd_device),
676 platform_get_snd_device_name(usecase->out_snd_device));
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800677
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800678 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700679 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800680 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
681 usecase_backend_idx == backend_idx) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530682 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
683 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700684 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700685 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 switch_device[usecase->id] = true;
687 num_uc_to_switch++;
688 }
689 }
690
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530691 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
692 num_uc_to_switch);
693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700695 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530697 /* Make sure the previous devices to be disabled first and then enable the
698 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 list_for_each(node, &adev->usecase_list) {
700 usecase = node_to_item(node, struct audio_usecase, list);
701 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 }
704 }
705
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700706 list_for_each(node, &adev->usecase_list) {
707 usecase = node_to_item(node, struct audio_usecase, list);
708 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700710 }
711 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 /* Re-route all the usecases on the shared backend other than the
714 specified usecase to new snd devices */
715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta36cc9e62015-08-04 14:45:37 +0530717 /* Update the out_snd_device only for the usecases that are enabled here */
718 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
719 usecase->out_snd_device = snd_device;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530720 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
721 use_case_table[usecase->id],
722 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530723 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700724 }
725 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700726 }
727}
728
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700729static void check_and_route_capture_usecases(struct audio_device *adev,
730 struct audio_usecase *uc_info,
731 snd_device_t snd_device)
732{
733 struct listnode *node;
734 struct audio_usecase *usecase;
735 bool switch_device[AUDIO_USECASE_MAX];
736 int i, num_uc_to_switch = 0;
737
738 /*
739 * This function is to make sure that all the active capture usecases
740 * are always routed to the same input sound device.
741 * For example, if audio-record and voice-call usecases are currently
742 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
743 * is received for voice call then we have to make sure that audio-record
744 * usecase is also switched to earpiece i.e. voice-dmic-ef,
745 * because of the limitation that two devices cannot be enabled
746 * at the same time if they share the same backend.
747 */
748 for (i = 0; i < AUDIO_USECASE_MAX; i++)
749 switch_device[i] = false;
750
751 list_for_each(node, &adev->usecase_list) {
752 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800753 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700754 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700755 usecase->in_snd_device != snd_device &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700756 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530757 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
758 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700759 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
761 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700762 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700763 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 switch_device[usecase->id] = true;
765 num_uc_to_switch++;
766 }
767 }
768
769 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700770 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700771
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530772 /* Make sure the previous devices to be disabled first and then enable the
773 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 list_for_each(node, &adev->usecase_list) {
775 usecase = node_to_item(node, struct audio_usecase, list);
776 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700777 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800778 }
779 }
780
781 list_for_each(node, &adev->usecase_list) {
782 usecase = node_to_item(node, struct audio_usecase, list);
783 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700784 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700785 }
786 }
787
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700788 /* Re-route all the usecases on the shared backend other than the
789 specified usecase to new snd devices */
790 list_for_each(node, &adev->usecase_list) {
791 usecase = node_to_item(node, struct audio_usecase, list);
792 /* Update the in_snd_device only before enabling the audio route */
793 if (switch_device[usecase->id] ) {
794 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800795 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530796 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700797 }
798 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 }
800}
801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800802/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700803static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700805 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700806 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807
808 switch (channels) {
809 /*
810 * Do not handle stereo output in Multi-channel cases
811 * Stereo case is handled in normal playback path
812 */
813 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700814 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
815 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
816 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
819 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800820 break;
821 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700822 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __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;
828 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829 break;
830 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700831 ALOGE("HDMI does not support multi channel playback");
832 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833 break;
834 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700835 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836}
837
Alexy Josephb1379942016-01-29 15:49:38 -0800838audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800839 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700840{
841 struct audio_usecase *usecase;
842 struct listnode *node;
843
844 list_for_each(node, &adev->usecase_list) {
845 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800846 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847 ALOGV("%s: usecase id %d", __func__, usecase->id);
848 return usecase->id;
849 }
850 }
851 return USECASE_INVALID;
852}
853
Alexy Josephb1379942016-01-29 15:49:38 -0800854struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700855 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856{
857 struct audio_usecase *usecase;
858 struct listnode *node;
859
860 list_for_each(node, &adev->usecase_list) {
861 usecase = node_to_item(node, struct audio_usecase, list);
862 if (usecase->id == uc_id)
863 return usecase;
864 }
865 return NULL;
866}
867
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530868/*
869 * is a true native playback active
870 */
871bool audio_is_true_native_stream_active(struct audio_device *adev)
872{
873 bool active = false;
874 int i = 0;
875 struct listnode *node;
876
877 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
878 ALOGV("%s:napb: not in true mode or non hdphones device",
879 __func__);
880 active = false;
881 goto exit;
882 }
883
884 list_for_each(node, &adev->usecase_list) {
885 struct audio_usecase *uc;
886 uc = node_to_item(node, struct audio_usecase, list);
887 struct stream_out *curr_out =
888 (struct stream_out*) uc->stream.out;
889
890 if (curr_out && PCM_PLAYBACK == uc->type) {
891 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
892 "(%d) device %s", __func__, i++, use_case_table[uc->id],
893 uc->id, curr_out->sample_rate,
894 curr_out->bit_width,
895 platform_get_snd_device_name(uc->out_snd_device));
896
897 if (is_offload_usecase(uc->id) &&
898 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
899 active = true;
900 ALOGD("%s:napb:native stream detected", __func__);
901 }
902 }
903 }
904exit:
905 return active;
906}
907
908
909static bool force_device_switch(struct audio_usecase *usecase)
910{
911 bool ret = false;
912 bool is_it_true_mode = false;
913
914 if (is_offload_usecase(usecase->id) &&
915 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +0800916 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
917 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
918 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530919 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
920 if ((is_it_true_mode && !adev->native_playback_enabled) ||
921 (!is_it_true_mode && adev->native_playback_enabled)){
922 ret = true;
923 ALOGD("napb: time to toggle native mode");
924 }
925 }
926
927 return ret;
928}
929
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700930int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800931{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800932 snd_device_t out_snd_device = SND_DEVICE_NONE;
933 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700934 struct audio_usecase *usecase = NULL;
935 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800936 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800937 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800938 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800939 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700940 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530942 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
943
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 usecase = get_usecase_from_list(adev, uc_id);
945 if (usecase == NULL) {
946 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
947 return -EINVAL;
948 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800949
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800950 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800951 (usecase->type == VOIP_CALL) ||
952 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700953 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800954 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700955 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 usecase->devices = usecase->stream.out->devices;
957 } else {
958 /*
959 * If the voice call is active, use the sound devices of voice call usecase
960 * so that it would not result any device switch. All the usecases will
961 * be switched to new device when select_devices() is called for voice call
962 * usecase. This is to avoid switching devices for voice call when
963 * check_usecases_codec_backend() is called below.
964 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -0800965 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700966 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800967 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700968 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
969 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 in_snd_device = vc_usecase->in_snd_device;
971 out_snd_device = vc_usecase->out_snd_device;
972 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800973 } else if (voice_extn_compress_voip_is_active(adev)) {
974 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700975 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530976 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700977 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800978 in_snd_device = voip_usecase->in_snd_device;
979 out_snd_device = voip_usecase->out_snd_device;
980 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800981 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800982 hfp_ucid = audio_extn_hfp_get_usecase();
983 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700984 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800985 in_snd_device = hfp_usecase->in_snd_device;
986 out_snd_device = hfp_usecase->out_snd_device;
987 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 }
989 if (usecase->type == PCM_PLAYBACK) {
990 usecase->devices = usecase->stream.out->devices;
991 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700992 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700993 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800994 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700995 if (usecase->stream.out == adev->primary_output &&
996 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800997 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700998 select_devices(adev, adev->active_input->usecase);
999 }
1000 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 } else if (usecase->type == PCM_CAPTURE) {
1002 usecase->devices = usecase->stream.in->device;
1003 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001004 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001005 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001006 if (adev->active_input &&
1007 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301008 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1009 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1010 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001011 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001012 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001013 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1014 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001015 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001016 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001017 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001018 }
1019 }
1020
1021 if (out_snd_device == usecase->out_snd_device &&
1022 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301023
1024 if (!force_device_switch(usecase))
1025 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 }
1027
sangwoobc677242013-08-08 16:53:43 +09001028 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001029 out_snd_device, platform_get_snd_device_name(out_snd_device),
1030 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 /*
1033 * Limitation: While in call, to do a device switch we need to disable
1034 * and enable both RX and TX devices though one of them is same as current
1035 * device.
1036 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001037 if ((usecase->type == VOICE_CALL) &&
1038 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1039 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001040 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001041 }
1042
1043 if (((usecase->type == VOICE_CALL) ||
1044 (usecase->type == VOIP_CALL)) &&
1045 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1046 /* Disable sidetone only if voice/voip call already exists */
1047 if (voice_is_call_state_active(adev) ||
1048 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001049 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001050 }
1051
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052 /* Disable current sound devices */
1053 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001054 disable_audio_route(adev, usecase);
1055 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056 }
1057
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001059 disable_audio_route(adev, usecase);
1060 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 }
1062
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001063 /* Applicable only on the targets that has external modem.
1064 * New device information should be sent to modem before enabling
1065 * the devices to reduce in-call device switch time.
1066 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001067 if ((usecase->type == VOICE_CALL) &&
1068 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1069 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001070 status = platform_switch_voice_call_enable_device_config(adev->platform,
1071 out_snd_device,
1072 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001073 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001074
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001075 /* Enable new sound devices */
1076 if (out_snd_device != SND_DEVICE_NONE) {
1077 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1078 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001079 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080 }
1081
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001082 if (in_snd_device != SND_DEVICE_NONE) {
1083 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001084 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001085 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086
Avinash Vaish71a8b972014-07-24 15:36:33 +05301087 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001088 status = platform_switch_voice_call_device_post(adev->platform,
1089 out_snd_device,
1090 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301091 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001092 /* Enable sidetone only if voice/voip call already exists */
1093 if (voice_is_call_state_active(adev) ||
1094 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001095 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301096 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001097
sangwoo170731f2013-06-08 15:36:36 +09001098 usecase->in_snd_device = in_snd_device;
1099 usecase->out_snd_device = out_snd_device;
1100
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301101 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001102 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301103 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001104 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301105 usecase->stream.out->flags,
1106 usecase->stream.out->format,
1107 usecase->stream.out->sample_rate,
1108 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301109 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301110 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001111 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301112 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001113
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001114 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001115
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001116 /* Applicable only on the targets that has external modem.
1117 * Enable device command should be sent to modem only after
1118 * enabling voice call mixer controls
1119 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001120 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001121 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1122 out_snd_device,
1123 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301124 ALOGD("%s: done",__func__);
1125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001126 return status;
1127}
1128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001129static int stop_input_stream(struct stream_in *in)
1130{
1131 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132 struct audio_usecase *uc_info;
1133 struct audio_device *adev = in->dev;
1134
Eric Laurentc8400632013-02-14 19:04:54 -08001135 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136
Eric Laurent994a6932013-07-17 11:51:42 -07001137 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139 uc_info = get_usecase_from_list(adev, in->usecase);
1140 if (uc_info == NULL) {
1141 ALOGE("%s: Could not find the usecase (%d) in the list",
1142 __func__, in->usecase);
1143 return -EINVAL;
1144 }
1145
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001146 /* Close in-call recording streams */
1147 voice_check_and_stop_incall_rec_usecase(adev, in);
1148
Eric Laurent150dbfe2013-02-27 14:31:02 -08001149 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001150 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151
1152 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001153 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001155 list_remove(&uc_info->list);
1156 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157
Eric Laurent994a6932013-07-17 11:51:42 -07001158 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159 return ret;
1160}
1161
1162int start_input_stream(struct stream_in *in)
1163{
1164 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001165 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001166 struct audio_usecase *uc_info;
1167 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301168 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169
Mingming Yin2664a5b2015-09-03 10:53:11 -07001170 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1171 if (get_usecase_from_list(adev, usecase) == NULL)
1172 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301173 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1174 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001175
Naresh Tanniru80659832014-06-04 18:17:56 +05301176
1177 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301178 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301179 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301180 goto error_config;
1181 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301182
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001183 /* Check if source matches incall recording usecase criteria */
1184 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1185 if (ret)
1186 goto error_config;
1187 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001188 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1189
1190 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1191 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1192 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1193 goto error_config;
1194 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001195
Eric Laurentb23d5282013-05-14 15:27:20 -07001196 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001197 if (in->pcm_device_id < 0) {
1198 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1199 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001200 ret = -EINVAL;
1201 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203
1204 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001205 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001206
1207 if (!uc_info) {
1208 ret = -ENOMEM;
1209 goto error_config;
1210 }
1211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001212 uc_info->id = in->usecase;
1213 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001214 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001215 uc_info->devices = in->device;
1216 uc_info->in_snd_device = SND_DEVICE_NONE;
1217 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001219 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301220 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1221 adev->perf_lock_opts,
1222 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224
Eric Laurentc8400632013-02-14 19:04:54 -08001225 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001226 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1227
1228 unsigned int flags = PCM_IN;
1229 unsigned int pcm_open_retry_count = 0;
1230
1231 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1232 flags |= PCM_MMAP | PCM_NOIRQ;
1233 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1234 }
1235
1236 while (1) {
1237 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1238 flags, &in->config);
1239 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1240 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1241 if (in->pcm != NULL) {
1242 pcm_close(in->pcm);
1243 in->pcm = NULL;
1244 }
1245 if (pcm_open_retry_count-- == 0) {
1246 ret = -EIO;
1247 goto error_open;
1248 }
1249 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1250 continue;
1251 }
1252 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001254
1255 ALOGV("%s: pcm_prepare", __func__);
1256 ret = pcm_prepare(in->pcm);
1257 if (ret < 0) {
1258 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1259 pcm_close(in->pcm);
1260 in->pcm = NULL;
1261 goto error_open;
1262 }
1263
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301264 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001265 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001266
Eric Laurentc8400632013-02-14 19:04:54 -08001267 return ret;
1268
1269error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301270 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001272error_config:
1273 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301274 /*
1275 * sleep 50ms to allow sufficient time for kernel
1276 * drivers to recover incases like SSR.
1277 */
1278 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001280
1281 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282}
1283
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001284void lock_input_stream(struct stream_in *in)
1285{
1286 pthread_mutex_lock(&in->pre_lock);
1287 pthread_mutex_lock(&in->lock);
1288 pthread_mutex_unlock(&in->pre_lock);
1289}
1290
1291void lock_output_stream(struct stream_out *out)
1292{
1293 pthread_mutex_lock(&out->pre_lock);
1294 pthread_mutex_lock(&out->lock);
1295 pthread_mutex_unlock(&out->pre_lock);
1296}
1297
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001298/* must be called with out->lock locked */
1299static int send_offload_cmd_l(struct stream_out* out, int command)
1300{
1301 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1302
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001303 if (!cmd) {
1304 ALOGE("failed to allocate mem for command 0x%x", command);
1305 return -ENOMEM;
1306 }
1307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001308 ALOGVV("%s %d", __func__, command);
1309
1310 cmd->cmd = command;
1311 list_add_tail(&out->offload_cmd_list, &cmd->node);
1312 pthread_cond_signal(&out->offload_cond);
1313 return 0;
1314}
1315
1316/* must be called iwth out->lock locked */
1317static void stop_compressed_output_l(struct stream_out *out)
1318{
1319 out->offload_state = OFFLOAD_STATE_IDLE;
1320 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001321 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001322 if (out->compr != NULL) {
1323 compress_stop(out->compr);
1324 while (out->offload_thread_blocked) {
1325 pthread_cond_wait(&out->cond, &out->lock);
1326 }
1327 }
1328}
1329
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001330bool is_offload_usecase(audio_usecase_t uc_id)
1331{
1332 unsigned int i;
1333 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1334 if (uc_id == offload_usecases[i])
1335 return true;
1336 }
1337 return false;
1338}
1339
vivek mehta446c3962015-09-14 10:57:35 -07001340static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001341{
vivek mehta446c3962015-09-14 10:57:35 -07001342 audio_usecase_t ret_uc = USECASE_INVALID;
1343 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001344 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001345 if (!adev->multi_offload_enable) {
1346 if (is_direct_pcm)
1347 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1348 else
1349 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001350
vivek mehta446c3962015-09-14 10:57:35 -07001351 pthread_mutex_lock(&adev->lock);
1352 if (get_usecase_from_list(adev, ret_uc) != NULL)
1353 ret_uc = USECASE_INVALID;
1354 pthread_mutex_unlock(&adev->lock);
1355
1356 return ret_uc;
1357 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001358
1359 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001360 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1361 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1362 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1363 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001364 break;
1365 }
1366 }
vivek mehta446c3962015-09-14 10:57:35 -07001367
1368 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1369 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001370}
1371
1372static void free_offload_usecase(struct audio_device *adev,
1373 audio_usecase_t uc_id)
1374{
vivek mehta446c3962015-09-14 10:57:35 -07001375 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001376 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001377
1378 if (!adev->multi_offload_enable)
1379 return;
1380
1381 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1382 if (offload_usecases[offload_uc_index] == uc_id) {
1383 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001384 break;
1385 }
1386 }
1387 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1388}
1389
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001390static void *offload_thread_loop(void *context)
1391{
1392 struct stream_out *out = (struct stream_out *) context;
1393 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001394 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001395
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001396 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1397 set_sched_policy(0, SP_FOREGROUND);
1398 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1399
1400 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001401 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001402 for (;;) {
1403 struct offload_cmd *cmd = NULL;
1404 stream_callback_event_t event;
1405 bool send_callback = false;
1406
1407 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1408 __func__, list_empty(&out->offload_cmd_list),
1409 out->offload_state);
1410 if (list_empty(&out->offload_cmd_list)) {
1411 ALOGV("%s SLEEPING", __func__);
1412 pthread_cond_wait(&out->offload_cond, &out->lock);
1413 ALOGV("%s RUNNING", __func__);
1414 continue;
1415 }
1416
1417 item = list_head(&out->offload_cmd_list);
1418 cmd = node_to_item(item, struct offload_cmd, node);
1419 list_remove(item);
1420
1421 ALOGVV("%s STATE %d CMD %d out->compr %p",
1422 __func__, out->offload_state, cmd->cmd, out->compr);
1423
1424 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1425 free(cmd);
1426 break;
1427 }
1428
1429 if (out->compr == NULL) {
1430 ALOGE("%s: Compress handle is NULL", __func__);
1431 pthread_cond_signal(&out->cond);
1432 continue;
1433 }
1434 out->offload_thread_blocked = true;
1435 pthread_mutex_unlock(&out->lock);
1436 send_callback = false;
1437 switch(cmd->cmd) {
1438 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001439 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001440 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001441 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001442 send_callback = true;
1443 event = STREAM_CBK_EVENT_WRITE_READY;
1444 break;
1445 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001446 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301447 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001448 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301449 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001450 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301451 if (ret < 0)
1452 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301453 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301454 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001455 compress_drain(out->compr);
1456 else
1457 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301458 if (ret != -ENETRESET) {
1459 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301460 pthread_mutex_lock(&out->lock);
1461 out->send_new_metadata = 1;
1462 out->send_next_track_params = true;
1463 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301464 event = STREAM_CBK_EVENT_DRAIN_READY;
1465 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1466 } else
1467 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001468 break;
1469 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001470 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001471 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001472 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473 send_callback = true;
1474 event = STREAM_CBK_EVENT_DRAIN_READY;
1475 break;
1476 default:
1477 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1478 break;
1479 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001480 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 out->offload_thread_blocked = false;
1482 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001483 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001484 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001485 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001486 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001487 free(cmd);
1488 }
1489
1490 pthread_cond_signal(&out->cond);
1491 while (!list_empty(&out->offload_cmd_list)) {
1492 item = list_head(&out->offload_cmd_list);
1493 list_remove(item);
1494 free(node_to_item(item, struct offload_cmd, node));
1495 }
1496 pthread_mutex_unlock(&out->lock);
1497
1498 return NULL;
1499}
1500
1501static int create_offload_callback_thread(struct stream_out *out)
1502{
1503 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1504 list_init(&out->offload_cmd_list);
1505 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1506 offload_thread_loop, out);
1507 return 0;
1508}
1509
1510static int destroy_offload_callback_thread(struct stream_out *out)
1511{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001512 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001513 stop_compressed_output_l(out);
1514 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1515
1516 pthread_mutex_unlock(&out->lock);
1517 pthread_join(out->offload_thread, (void **) NULL);
1518 pthread_cond_destroy(&out->offload_cond);
1519
1520 return 0;
1521}
1522
Eric Laurent07eeafd2013-10-06 12:52:49 -07001523static bool allow_hdmi_channel_config(struct audio_device *adev)
1524{
1525 struct listnode *node;
1526 struct audio_usecase *usecase;
1527 bool ret = true;
1528
1529 list_for_each(node, &adev->usecase_list) {
1530 usecase = node_to_item(node, struct audio_usecase, list);
1531 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1532 /*
1533 * If voice call is already existing, do not proceed further to avoid
1534 * disabling/enabling both RX and TX devices, CSD calls, etc.
1535 * Once the voice call done, the HDMI channels can be configured to
1536 * max channels of remaining use cases.
1537 */
1538 if (usecase->id == USECASE_VOICE_CALL) {
1539 ALOGD("%s: voice call is active, no change in HDMI channels",
1540 __func__);
1541 ret = false;
1542 break;
1543 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1544 ALOGD("%s: multi channel playback is active, "
1545 "no change in HDMI channels", __func__);
1546 ret = false;
1547 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001548 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001549 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001550 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1551 ", no change in HDMI channels", __func__,
1552 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001553 ret = false;
1554 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001555 }
1556 }
1557 }
1558 return ret;
1559}
1560
1561static int check_and_set_hdmi_channels(struct audio_device *adev,
1562 unsigned int channels)
1563{
1564 struct listnode *node;
1565 struct audio_usecase *usecase;
1566
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001567 unsigned int supported_channels = platform_edid_get_max_channels(
1568 adev->platform);
1569 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001570 /* Check if change in HDMI channel config is allowed */
1571 if (!allow_hdmi_channel_config(adev))
1572 return 0;
1573
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001574 if (channels > supported_channels)
1575 channels = supported_channels;
1576
Eric Laurent07eeafd2013-10-06 12:52:49 -07001577 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001578 ALOGD("%s: Requested channels are same as current channels(%d)",
1579 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001580 return 0;
1581 }
1582
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001583 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001584 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001585 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001586 adev->cur_hdmi_channels = channels;
1587
1588 /*
1589 * Deroute all the playback streams routed to HDMI so that
1590 * the back end is deactivated. Note that backend will not
1591 * be deactivated if any one stream is connected to it.
1592 */
1593 list_for_each(node, &adev->usecase_list) {
1594 usecase = node_to_item(node, struct audio_usecase, list);
1595 if (usecase->type == PCM_PLAYBACK &&
1596 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001597 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001598 }
1599 }
1600
1601 /*
1602 * Enable all the streams disabled above. Now the HDMI backend
1603 * will be activated with new channel configuration
1604 */
1605 list_for_each(node, &adev->usecase_list) {
1606 usecase = node_to_item(node, struct audio_usecase, list);
1607 if (usecase->type == PCM_PLAYBACK &&
1608 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001609 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001610 }
1611 }
1612
1613 return 0;
1614}
1615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616static int stop_output_stream(struct stream_out *out)
1617{
1618 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 struct audio_usecase *uc_info;
1620 struct audio_device *adev = out->dev;
1621
Eric Laurent994a6932013-07-17 11:51:42 -07001622 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001623 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 uc_info = get_usecase_from_list(adev, out->usecase);
1625 if (uc_info == NULL) {
1626 ALOGE("%s: Could not find the usecase (%d) in the list",
1627 __func__, out->usecase);
1628 return -EINVAL;
1629 }
1630
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001631 if (is_offload_usecase(out->usecase) &&
1632 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001633 if (adev->visualizer_stop_output != NULL)
1634 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001635
1636 audio_extn_dts_remove_state_notifier_node(out->usecase);
1637
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001638 if (adev->offload_effects_stop_output != NULL)
1639 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1640 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001641
Eric Laurent150dbfe2013-02-27 14:31:02 -08001642 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001643 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644
1645 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001646 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001648 list_remove(&uc_info->list);
1649 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001651 if (is_offload_usecase(out->usecase) &&
1652 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1653 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1654 ALOGV("Disable passthrough , reset mixer to pcm");
1655 /* NO_PASSTHROUGH */
1656 out->compr_config.codec->compr_passthr = 0;
1657 audio_extn_dolby_set_hdmi_config(adev, out);
1658 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1659 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001660 /* Must be called after removing the usecase from list */
1661 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1662 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1663
Eric Laurent994a6932013-07-17 11:51:42 -07001664 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 return ret;
1666}
1667
1668int start_output_stream(struct stream_out *out)
1669{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001671 int sink_channels = 0;
1672 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 struct audio_usecase *uc_info;
1674 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301675 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001677 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1678 ret = -EINVAL;
1679 goto error_config;
1680 }
1681
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301682 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1683 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1684 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301685
Naresh Tanniru80659832014-06-04 18:17:56 +05301686 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301687 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301688 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301689 goto error_config;
1690 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301691
Eric Laurentb23d5282013-05-14 15:27:20 -07001692 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693 if (out->pcm_device_id < 0) {
1694 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1695 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001696 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001697 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698 }
1699
1700 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001701
1702 if (!uc_info) {
1703 ret = -ENOMEM;
1704 goto error_config;
1705 }
1706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 uc_info->id = out->usecase;
1708 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001709 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710 uc_info->devices = out->devices;
1711 uc_info->in_snd_device = SND_DEVICE_NONE;
1712 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001713 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001714 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001715 if (is_offload_usecase(out->usecase)) {
1716 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001717 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1718 }
1719 }
Mingming Yin9c041392014-05-01 15:37:31 -07001720 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1721 if (!strncmp("true", prop_value, 4)) {
1722 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001723 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1724 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001725 check_and_set_hdmi_channels(adev, sink_channels);
1726 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001727 if (is_offload_usecase(out->usecase)) {
1728 unsigned int ch_count = out->compr_config.codec->ch_in;
1729 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1730 /* backend channel config for passthrough stream is stereo */
1731 ch_count = 2;
1732 check_and_set_hdmi_channels(adev, ch_count);
1733 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001734 check_and_set_hdmi_channels(adev, out->config.channels);
1735 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001736 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001737 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001738 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301740 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1741 adev->perf_lock_opts,
1742 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001743 select_devices(adev, out->usecase);
1744
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001745 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1746 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001747 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001748 unsigned int flags = PCM_OUT;
1749 unsigned int pcm_open_retry_count = 0;
1750 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1751 flags |= PCM_MMAP | PCM_NOIRQ;
1752 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1753 } else
1754 flags |= PCM_MONOTONIC;
1755
1756 while (1) {
1757 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1758 flags, &out->config);
1759 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1760 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1761 if (out->pcm != NULL) {
1762 pcm_close(out->pcm);
1763 out->pcm = NULL;
1764 }
1765 if (pcm_open_retry_count-- == 0) {
1766 ret = -EIO;
1767 goto error_open;
1768 }
1769 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1770 continue;
1771 }
1772 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001774
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001775 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1776 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001777
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001778 ALOGV("%s: pcm_prepare", __func__);
1779 if (pcm_is_ready(out->pcm)) {
1780 ret = pcm_prepare(out->pcm);
1781 if (ret < 0) {
1782 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1783 pcm_close(out->pcm);
1784 out->pcm = NULL;
1785 goto error_open;
1786 }
1787 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001789 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1790 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001792 out->compr = compress_open(adev->snd_card,
1793 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 COMPRESS_IN, &out->compr_config);
1795 if (out->compr && !is_compress_ready(out->compr)) {
1796 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1797 compress_close(out->compr);
1798 out->compr = NULL;
1799 ret = -EIO;
1800 goto error_open;
1801 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301802 /* compress_open sends params of the track, so reset the flag here */
1803 out->is_compr_metadata_avail = false;
1804
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 if (out->offload_callback)
1806 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001807
Fred Oh3f43e742015-03-04 18:42:34 -08001808 /* Since small bufs uses blocking writes, a write will be blocked
1809 for the default max poll time (20s) in the event of an SSR.
1810 Reduce the poll time to observe and deal with SSR faster.
1811 */
1812 if (out->use_small_bufs) {
1813 compress_set_max_poll_wait(out->compr, 1000);
1814 }
1815
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001816 audio_extn_dts_create_state_notifier_node(out->usecase);
1817 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1818 popcount(out->channel_mask),
1819 out->playback_started);
1820
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001821#ifdef DS1_DOLBY_DDP_ENABLED
1822 if (audio_extn_is_dolby_format(out->format))
1823 audio_extn_dolby_send_ddp_endp_params(adev);
1824#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001825 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1826 if (adev->visualizer_start_output != NULL)
1827 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1828 if (adev->offload_effects_start_output != NULL)
1829 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001830 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001831 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301833 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001834 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301838 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001840error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301841 /*
1842 * sleep 50ms to allow sufficient time for kernel
1843 * drivers to recover incases like SSR.
1844 */
1845 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001846 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847}
1848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849static int check_input_parameters(uint32_t sample_rate,
1850 audio_format_t format,
1851 int channel_count)
1852{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001853 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001855 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001856 !voice_extn_compress_voip_is_format_supported(format) &&
1857 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001858
1859 switch (channel_count) {
1860 case 1:
1861 case 2:
1862 case 6:
1863 break;
1864 default:
1865 ret = -EINVAL;
1866 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867
1868 switch (sample_rate) {
1869 case 8000:
1870 case 11025:
1871 case 12000:
1872 case 16000:
1873 case 22050:
1874 case 24000:
1875 case 32000:
1876 case 44100:
1877 case 48000:
1878 break;
1879 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001880 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
1882
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001883 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884}
1885
1886static size_t get_input_buffer_size(uint32_t sample_rate,
1887 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001888 int channel_count,
1889 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001890{
1891 size_t size = 0;
1892
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001893 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1894 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001896 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001897 if (is_low_latency)
1898 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001899 /* ToDo: should use frame_size computed based on the format and
1900 channel_count here. */
1901 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001903 /* make sure the size is multiple of 32 bytes
1904 * At 48 kHz mono 16-bit PCM:
1905 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1906 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1907 */
1908 size += 0x1f;
1909 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001910
1911 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912}
1913
1914static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1915{
1916 struct stream_out *out = (struct stream_out *)stream;
1917
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001918 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919}
1920
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001921static int out_set_sample_rate(struct audio_stream *stream __unused,
1922 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923{
1924 return -ENOSYS;
1925}
1926
1927static size_t out_get_buffer_size(const struct audio_stream *stream)
1928{
1929 struct stream_out *out = (struct stream_out *)stream;
1930
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001931 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001933 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1934 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001935
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001936 return out->config.period_size *
1937 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938}
1939
1940static uint32_t out_get_channels(const struct audio_stream *stream)
1941{
1942 struct stream_out *out = (struct stream_out *)stream;
1943
1944 return out->channel_mask;
1945}
1946
1947static audio_format_t out_get_format(const struct audio_stream *stream)
1948{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001949 struct stream_out *out = (struct stream_out *)stream;
1950
1951 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952}
1953
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001954static int out_set_format(struct audio_stream *stream __unused,
1955 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956{
1957 return -ENOSYS;
1958}
1959
1960static int out_standby(struct audio_stream *stream)
1961{
1962 struct stream_out *out = (struct stream_out *)stream;
1963 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301965 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1966 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001967 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1968 /* Ignore standby in case of voip call because the voip output
1969 * stream is closed in adev_close_output_stream()
1970 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301971 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001972 return 0;
1973 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001975 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001977 if (adev->adm_deregister_stream)
1978 adev->adm_deregister_stream(adev->adm_data, out->handle);
1979
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001980 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001982 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983 if (out->pcm) {
1984 pcm_close(out->pcm);
1985 out->pcm = NULL;
1986 }
1987 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001988 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001989 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301990 out->send_next_track_params = false;
1991 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001992 out->gapless_mdata.encoder_delay = 0;
1993 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001994 if (out->compr != NULL) {
1995 compress_close(out->compr);
1996 out->compr = NULL;
1997 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001998 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002000 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 }
2002 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302003 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 return 0;
2005}
2006
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002007static int out_dump(const struct audio_stream *stream __unused,
2008 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009{
2010 return 0;
2011}
2012
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002013static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2014{
2015 int ret = 0;
2016 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002017
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002018 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002019 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002020 return -EINVAL;
2021 }
2022
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302023 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002024
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002025 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2026 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302027 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002028 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002029 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2030 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302031 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002032 }
2033
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002034 ALOGV("%s new encoder delay %u and padding %u", __func__,
2035 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2036
2037 return 0;
2038}
2039
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002040static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2041{
2042 return out == adev->primary_output || out == adev->voice_tx_output;
2043}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2046{
2047 struct stream_out *out = (struct stream_out *)stream;
2048 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002049 struct audio_usecase *usecase;
2050 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051 struct str_parms *parms;
2052 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002053 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002054 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055
sangwoobc677242013-08-08 16:53:43 +09002056 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002057 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302059 if (!parms)
2060 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002061 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2062 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002064 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002065 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002067 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302068 * When HDMI cable is unplugged/usb hs is disconnected the
2069 * music playback is paused and the policy manager sends routing=0
2070 * But the audioflingercontinues to write data until standby time
2071 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002072 * Avoid this by routing audio to speaker until standby.
2073 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302074 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2075 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002076 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002077 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2078 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002079 }
2080
2081 /*
2082 * select_devices() call below switches all the usecases on the same
2083 * backend to the new device. Refer to check_usecases_codec_backend() in
2084 * the select_devices(). But how do we undo this?
2085 *
2086 * For example, music playback is active on headset (deep-buffer usecase)
2087 * and if we go to ringtones and select a ringtone, low-latency usecase
2088 * will be started on headset+speaker. As we can't enable headset+speaker
2089 * and headset devices at the same time, select_devices() switches the music
2090 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2091 * So when the ringtone playback is completed, how do we undo the same?
2092 *
2093 * We are relying on the out_set_parameters() call on deep-buffer output,
2094 * once the ringtone playback is ended.
2095 * NOTE: We should not check if the current devices are same as new devices.
2096 * Because select_devices() must be called to switch back the music
2097 * playback to headset.
2098 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002099 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002100 out->devices = val;
2101
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302102 if (!out->standby) {
2103 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2104 adev->perf_lock_opts,
2105 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302107 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2108 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002109
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002110 if (output_drives_call(adev, out)) {
2111 if(!voice_is_in_call(adev)) {
2112 if (adev->mode == AUDIO_MODE_IN_CALL) {
2113 adev->current_call_output = out;
2114 ret = voice_start_call(adev);
2115 }
2116 } else {
2117 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002118 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002119 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002120 }
2121 }
2122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002124 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002126
2127 if (out == adev->primary_output) {
2128 pthread_mutex_lock(&adev->lock);
2129 audio_extn_set_parameters(adev, parms);
2130 pthread_mutex_unlock(&adev->lock);
2131 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002132 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002133 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002134 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002135
2136 audio_extn_dts_create_state_notifier_node(out->usecase);
2137 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2138 popcount(out->channel_mask),
2139 out->playback_started);
2140
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002141 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002142 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302145error:
Eric Laurent994a6932013-07-17 11:51:42 -07002146 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147 return ret;
2148}
2149
2150static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2151{
2152 struct stream_out *out = (struct stream_out *)stream;
2153 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002154 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 char value[256];
2156 struct str_parms *reply = str_parms_create();
2157 size_t i, j;
2158 int ret;
2159 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002160
2161 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002162 if (reply) {
2163 str_parms_destroy(reply);
2164 }
2165 if (query) {
2166 str_parms_destroy(query);
2167 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002168 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2169 return NULL;
2170 }
2171
Eric Laurent994a6932013-07-17 11:51:42 -07002172 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2174 if (ret >= 0) {
2175 value[0] = '\0';
2176 i = 0;
2177 while (out->supported_channel_masks[i] != 0) {
2178 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2179 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2180 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002181 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002183 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 first = false;
2185 break;
2186 }
2187 }
2188 i++;
2189 }
2190 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2191 str = str_parms_to_str(reply);
2192 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002193 voice_extn_out_get_parameters(out, query, reply);
2194 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002195 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002196 free(str);
2197 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002200
Alexy Joseph62142aa2015-11-16 15:10:34 -08002201
2202 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2203 if (ret >= 0) {
2204 value[0] = '\0';
2205 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2206 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302207 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002208 } else {
2209 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302210 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002211 }
2212 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002213 if (str)
2214 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002215 str = str_parms_to_str(reply);
2216 }
2217
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002218 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2219 if (ret >= 0) {
2220 value[0] = '\0';
2221 i = 0;
2222 first = true;
2223 while (out->supported_formats[i] != 0) {
2224 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2225 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2226 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002227 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002228 }
2229 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2230 first = false;
2231 break;
2232 }
2233 }
2234 i++;
2235 }
2236 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002237 if (str)
2238 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002239 str = str_parms_to_str(reply);
2240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 str_parms_destroy(query);
2242 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002243 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 return str;
2245}
2246
2247static uint32_t out_get_latency(const struct audio_stream_out *stream)
2248{
2249 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002250 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251
Alexy Josephaa54c872014-12-03 02:46:47 -08002252 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002253 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002254 } else {
2255 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002257 }
2258
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302259 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002260 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261}
2262
2263static int out_set_volume(struct audio_stream_out *stream, float left,
2264 float right)
2265{
Eric Laurenta9024de2013-04-04 09:19:12 -07002266 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002267 int volume[2];
2268
Eric Laurenta9024de2013-04-04 09:19:12 -07002269 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2270 /* only take left channel into account: the API is for stereo anyway */
2271 out->muted = (left == 0.0f);
2272 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002273 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002274 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2275 /*
2276 * Set mute or umute on HDMI passthrough stream.
2277 * Only take left channel into account.
2278 * Mute is 0 and unmute 1
2279 */
2280 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2281 } else {
2282 char mixer_ctl_name[128];
2283 struct audio_device *adev = out->dev;
2284 struct mixer_ctl *ctl;
2285 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002286 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002288 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2289 "Compress Playback %d Volume", pcm_device_id);
2290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2291 if (!ctl) {
2292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2293 __func__, mixer_ctl_name);
2294 return -EINVAL;
2295 }
2296 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2297 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2298 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2299 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002301 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 return -ENOSYS;
2304}
2305
2306static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2307 size_t bytes)
2308{
2309 struct stream_out *out = (struct stream_out *)stream;
2310 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302311 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002312 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002314 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302315
Naresh Tanniru80659832014-06-04 18:17:56 +05302316 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002317
Ashish Jainbbce4322016-02-16 13:25:27 +05302318 if (is_offload_usecase(out->usecase)) {
2319 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302320 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2321 pthread_mutex_unlock(&out->lock);
2322 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302323 } else {
2324 /* increase written size during SSR to avoid mismatch
2325 * with the written frames count in AF
2326 */
2327 out->written += bytes / (out->config.channels * sizeof(short));
2328 ALOGD(" %s: sound card is not active/SSR state", __func__);
2329 ret= -EIO;
2330 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302331 }
2332 }
2333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002335 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002336 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002337 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2338 ret = voice_extn_compress_voip_start_output_stream(out);
2339 else
2340 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002341 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002344 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 goto exit;
2346 }
vivek mehta446c3962015-09-14 10:57:35 -07002347 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002348 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350
Ashish Jain81eb2a82015-05-13 10:52:34 +05302351 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002352 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302353 adev->is_channel_status_set = true;
2354 }
2355
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002356 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002357 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002358 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002359 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002360 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2361 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302362 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2363 ALOGD("copl(%p):send next track params in gapless", out);
2364 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2365 out->send_next_track_params = false;
2366 out->is_compr_metadata_avail = false;
2367 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002368 }
2369
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302371 if (ret < 0)
2372 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002373 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002374 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302375 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302377 } else if (-ENETRESET == ret) {
2378 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2379 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2380 pthread_mutex_unlock(&out->lock);
2381 out_standby(&out->stream.common);
2382 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302384 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002386 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 out->playback_started = 1;
2388 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002389
2390 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2391 popcount(out->channel_mask),
2392 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 }
2394 pthread_mutex_unlock(&out->lock);
2395 return ret;
2396 } else {
2397 if (out->pcm) {
2398 if (out->muted)
2399 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002400
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002402
2403 if (adev->adm_request_focus)
2404 adev->adm_request_focus(adev->adm_data, out->handle);
2405
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002406 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2407 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2408 else
2409 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002410
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302411 if (ret < 0)
2412 ret = -errno;
2413 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002414 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002415
2416 if (adev->adm_abandon_focus)
2417 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419 }
2420
2421exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302422 /* ToDo: There may be a corner case when SSR happens back to back during
2423 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302424 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302425 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302426 }
2427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428 pthread_mutex_unlock(&out->lock);
2429
2430 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002431 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002432 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302433 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302434 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302435 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302436 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302437 out->standby = true;
2438 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302440 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302441 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 }
2443 return bytes;
2444}
2445
2446static int out_get_render_position(const struct audio_stream_out *stream,
2447 uint32_t *dsp_frames)
2448{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302450 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002451
2452 if (dsp_frames == NULL)
2453 return -EINVAL;
2454
2455 *dsp_frames = 0;
2456 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002457 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002458 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002459 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302460 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302462 if (ret < 0)
2463 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002464 ALOGVV("%s rendered frames %d sample_rate %d",
2465 __func__, *dsp_frames, out->sample_rate);
2466 }
2467 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302468 if (-ENETRESET == ret) {
2469 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2470 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2471 return -EINVAL;
2472 } else if(ret < 0) {
2473 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2474 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302475 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2476 /*
2477 * Handle corner case where compress session is closed during SSR
2478 * and timestamp is queried
2479 */
2480 ALOGE(" ERROR: sound card not active, return error");
2481 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302482 } else {
2483 return 0;
2484 }
Zhou Song32a556e2015-05-05 10:46:56 +08002485 } else if (audio_is_linear_pcm(out->format)) {
2486 *dsp_frames = out->written;
2487 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488 } else
2489 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490}
2491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002492static int out_add_audio_effect(const struct audio_stream *stream __unused,
2493 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494{
2495 return 0;
2496}
2497
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002498static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2499 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500{
2501 return 0;
2502}
2503
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002504static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2505 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506{
2507 return -EINVAL;
2508}
2509
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002510static int out_get_presentation_position(const struct audio_stream_out *stream,
2511 uint64_t *frames, struct timespec *timestamp)
2512{
2513 struct stream_out *out = (struct stream_out *)stream;
2514 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002515 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002516
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002517 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002518
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002519 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002520 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302521 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002522 &out->sample_rate);
2523 ALOGVV("%s rendered frames %ld sample_rate %d",
2524 __func__, dsp_frames, out->sample_rate);
2525 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302526 if (ret < 0)
2527 ret = -errno;
2528 if (-ENETRESET == ret) {
2529 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2530 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2531 ret = -EINVAL;
2532 } else
2533 ret = 0;
2534
Eric Laurent949a0892013-09-20 09:20:13 -07002535 /* this is the best we can do */
2536 clock_gettime(CLOCK_MONOTONIC, timestamp);
2537 }
2538 } else {
2539 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002540 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002541 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2542 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002543 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002544 // This adjustment accounts for buffering after app processor.
2545 // It is based on estimated DSP latency per use case, rather than exact.
2546 signed_frames -=
2547 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2548
Eric Laurent949a0892013-09-20 09:20:13 -07002549 // It would be unusual for this value to be negative, but check just in case ...
2550 if (signed_frames >= 0) {
2551 *frames = signed_frames;
2552 ret = 0;
2553 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002554 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302555 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2556 *frames = out->written;
2557 clock_gettime(CLOCK_MONOTONIC, timestamp);
2558 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002559 }
2560 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002561 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002562 return ret;
2563}
2564
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002565static int out_set_callback(struct audio_stream_out *stream,
2566 stream_callback_t callback, void *cookie)
2567{
2568 struct stream_out *out = (struct stream_out *)stream;
2569
2570 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002571 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 out->offload_callback = callback;
2573 out->offload_cookie = cookie;
2574 pthread_mutex_unlock(&out->lock);
2575 return 0;
2576}
2577
2578static int out_pause(struct audio_stream_out* stream)
2579{
2580 struct stream_out *out = (struct stream_out *)stream;
2581 int status = -ENOSYS;
2582 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002583 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002584 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002585 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002586 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302587 struct audio_device *adev = out->dev;
2588 int snd_scard_state = get_snd_card_state(adev);
2589
2590 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2591 status = compress_pause(out->compr);
2592
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002593 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002594
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302595 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002596 audio_extn_dts_notify_playback_state(out->usecase, 0,
2597 out->sample_rate, popcount(out->channel_mask),
2598 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002599 }
2600 pthread_mutex_unlock(&out->lock);
2601 }
2602 return status;
2603}
2604
2605static int out_resume(struct audio_stream_out* stream)
2606{
2607 struct stream_out *out = (struct stream_out *)stream;
2608 int status = -ENOSYS;
2609 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002610 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002611 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002612 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002613 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302615 struct audio_device *adev = out->dev;
2616 int snd_scard_state = get_snd_card_state(adev);
2617
2618 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2619 status = compress_resume(out->compr);
2620
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002621 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002622
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302623 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002624 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2625 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002626 }
2627 pthread_mutex_unlock(&out->lock);
2628 }
2629 return status;
2630}
2631
2632static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2633{
2634 struct stream_out *out = (struct stream_out *)stream;
2635 int status = -ENOSYS;
2636 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002637 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002638 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002639 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2640 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2641 else
2642 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2643 pthread_mutex_unlock(&out->lock);
2644 }
2645 return status;
2646}
2647
2648static int out_flush(struct audio_stream_out* stream)
2649{
2650 struct stream_out *out = (struct stream_out *)stream;
2651 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002652 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002653 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002654 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002655 stop_compressed_output_l(out);
2656 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002657 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 return 0;
2659 }
2660 return -ENOSYS;
2661}
2662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663/** audio_stream_in implementation **/
2664static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2665{
2666 struct stream_in *in = (struct stream_in *)stream;
2667
2668 return in->config.rate;
2669}
2670
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002671static int in_set_sample_rate(struct audio_stream *stream __unused,
2672 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673{
2674 return -ENOSYS;
2675}
2676
2677static size_t in_get_buffer_size(const struct audio_stream *stream)
2678{
2679 struct stream_in *in = (struct stream_in *)stream;
2680
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002681 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2682 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002683 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2684 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002685
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002686 return in->config.period_size *
2687 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688}
2689
2690static uint32_t in_get_channels(const struct audio_stream *stream)
2691{
2692 struct stream_in *in = (struct stream_in *)stream;
2693
2694 return in->channel_mask;
2695}
2696
2697static audio_format_t in_get_format(const struct audio_stream *stream)
2698{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002699 struct stream_in *in = (struct stream_in *)stream;
2700
2701 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702}
2703
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002704static int in_set_format(struct audio_stream *stream __unused,
2705 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706{
2707 return -ENOSYS;
2708}
2709
2710static int in_standby(struct audio_stream *stream)
2711{
2712 struct stream_in *in = (struct stream_in *)stream;
2713 struct audio_device *adev = in->dev;
2714 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302715 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2716 stream, in->usecase, use_case_table[in->usecase]);
2717
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002718 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2719 /* Ignore standby in case of voip call because the voip input
2720 * stream is closed in adev_close_input_stream()
2721 */
2722 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2723 return status;
2724 }
2725
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002726 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002727 if (!in->standby && in->is_st_session) {
2728 ALOGD("%s: sound trigger pcm stop lab", __func__);
2729 audio_extn_sound_trigger_stop_lab(in);
2730 in->standby = 1;
2731 }
2732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002734 if (adev->adm_deregister_stream)
2735 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2736
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002737 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002739 if (in->pcm) {
2740 pcm_close(in->pcm);
2741 in->pcm = NULL;
2742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002744 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 }
2746 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002747 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 return status;
2749}
2750
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002751static int in_dump(const struct audio_stream *stream __unused,
2752 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753{
2754 return 0;
2755}
2756
2757static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2758{
2759 struct stream_in *in = (struct stream_in *)stream;
2760 struct audio_device *adev = in->dev;
2761 struct str_parms *parms;
2762 char *str;
2763 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002764 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302766 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 parms = str_parms_create_str(kvpairs);
2768
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302769 if (!parms)
2770 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002771 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002772 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002773
2774 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2775 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 val = atoi(value);
2777 /* no audio source uses val == 0 */
2778 if ((in->source != val) && (val != 0)) {
2779 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002780 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2781 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2782 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2783 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002784 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002785 err = voice_extn_compress_voip_open_input_stream(in);
2786 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002787 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002788 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002789 }
2790 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 }
2792 }
2793
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002794 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2795 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002797 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 in->device = val;
2799 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002800 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002801 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 }
2803 }
2804
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002805done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002807 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808
2809 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302810error:
Eric Laurent994a6932013-07-17 11:51:42 -07002811 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 return ret;
2813}
2814
2815static char* in_get_parameters(const struct audio_stream *stream,
2816 const char *keys)
2817{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002818 struct stream_in *in = (struct stream_in *)stream;
2819 struct str_parms *query = str_parms_create_str(keys);
2820 char *str;
2821 char value[256];
2822 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002823
2824 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002825 if (reply) {
2826 str_parms_destroy(reply);
2827 }
2828 if (query) {
2829 str_parms_destroy(query);
2830 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002831 ALOGE("in_get_parameters: failed to create query or reply");
2832 return NULL;
2833 }
2834
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002835 ALOGV("%s: enter: keys - %s", __func__, keys);
2836
2837 voice_extn_in_get_parameters(in, query, reply);
2838
2839 str = str_parms_to_str(reply);
2840 str_parms_destroy(query);
2841 str_parms_destroy(reply);
2842
2843 ALOGV("%s: exit: returns - %s", __func__, str);
2844 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845}
2846
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002847static int in_set_gain(struct audio_stream_in *stream __unused,
2848 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849{
2850 return 0;
2851}
2852
2853static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2854 size_t bytes)
2855{
2856 struct stream_in *in = (struct stream_in *)stream;
2857 struct audio_device *adev = in->dev;
2858 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302859 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002861 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302862
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002863 if (in->is_st_session) {
2864 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2865 /* Read from sound trigger HAL */
2866 audio_extn_sound_trigger_read(in, buffer, bytes);
2867 pthread_mutex_unlock(&in->lock);
2868 return bytes;
2869 }
2870
Ashish Jainbbce4322016-02-16 13:25:27 +05302871 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002872 ALOGD(" %s: sound card is not active/SSR state", __func__);
2873 ret= -EIO;;
2874 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302875 }
2876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002878 pthread_mutex_lock(&adev->lock);
2879 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2880 ret = voice_extn_compress_voip_start_input_stream(in);
2881 else
2882 ret = start_input_stream(in);
2883 pthread_mutex_unlock(&adev->lock);
2884 if (ret != 0) {
2885 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 }
2887 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002888 if (adev->adm_register_input_stream)
2889 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002892 if (adev->adm_request_focus)
2893 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002896 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002897 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002898 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2899 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002900 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2901 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002902 else
2903 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302904 if (ret < 0)
2905 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002906 }
2907
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002908 if (adev->adm_abandon_focus)
2909 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2910
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 /*
2912 * Instead of writing zeroes here, we could trust the hardware
2913 * to always provide zeroes when muted.
2914 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302915 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2916 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 memset(buffer, 0, bytes);
2918
2919exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302920 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302921 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002922 if (-ENETRESET == ret)
2923 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 pthread_mutex_unlock(&in->lock);
2926
2927 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302928 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302929 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302930 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302931 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302932 in->standby = true;
2933 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302934 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002936 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05302937 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302938 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 }
2940 return bytes;
2941}
2942
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002943static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944{
2945 return 0;
2946}
2947
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002948static int add_remove_audio_effect(const struct audio_stream *stream,
2949 effect_handle_t effect,
2950 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002952 struct stream_in *in = (struct stream_in *)stream;
2953 int status = 0;
2954 effect_descriptor_t desc;
2955
2956 status = (*effect)->get_descriptor(effect, &desc);
2957 if (status != 0)
2958 return status;
2959
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002960 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002961 pthread_mutex_lock(&in->dev->lock);
2962 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2963 in->enable_aec != enable &&
2964 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2965 in->enable_aec = enable;
2966 if (!in->standby)
2967 select_devices(in->dev, in->usecase);
2968 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002969 if (in->enable_ns != enable &&
2970 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2971 in->enable_ns = enable;
2972 if (!in->standby)
2973 select_devices(in->dev, in->usecase);
2974 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002975 pthread_mutex_unlock(&in->dev->lock);
2976 pthread_mutex_unlock(&in->lock);
2977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 return 0;
2979}
2980
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002981static int in_add_audio_effect(const struct audio_stream *stream,
2982 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983{
Eric Laurent994a6932013-07-17 11:51:42 -07002984 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002985 return add_remove_audio_effect(stream, effect, true);
2986}
2987
2988static int in_remove_audio_effect(const struct audio_stream *stream,
2989 effect_handle_t effect)
2990{
Eric Laurent994a6932013-07-17 11:51:42 -07002991 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002992 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993}
2994
2995static int adev_open_output_stream(struct audio_hw_device *dev,
2996 audio_io_handle_t handle,
2997 audio_devices_t devices,
2998 audio_output_flags_t flags,
2999 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003000 struct audio_stream_out **stream_out,
3001 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002{
3003 struct audio_device *adev = (struct audio_device *)dev;
3004 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003005 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003006 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303009
3010 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3011 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003012 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303013 return -EINVAL;
3014 }
3015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3017
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303018 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3019 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
3020 devices, flags, &out->stream);
3021
3022
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003023 if (!out) {
3024 return -ENOMEM;
3025 }
3026
Haynes Mathew George204045b2015-02-25 20:32:03 -08003027 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003028 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003029 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 if (devices == AUDIO_DEVICE_NONE)
3032 devices = AUDIO_DEVICE_OUT_SPEAKER;
3033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 out->flags = flags;
3035 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003036 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003037 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003038 out->sample_rate = config->sample_rate;
3039 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3040 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003041 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003042 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003043 out->non_blocking = 0;
3044 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045
3046 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003047 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303048 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3049 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003050 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3051 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3052
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003053 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003054 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3055 ret = read_hdmi_channel_masks(out);
3056
3057 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3058 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003059 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003060 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003061 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003062
3063 if (config->sample_rate == 0)
3064 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3065 if (config->channel_mask == 0)
3066 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3067
3068 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3071 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003073 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3076 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003077 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 ret = voice_extn_compress_voip_open_output_stream(out);
3079 if (ret != 0) {
3080 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3081 __func__, ret);
3082 goto error_open;
3083 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003084 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3085 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3086
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3088 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3089 ALOGE("%s: Unsupported Offload information", __func__);
3090 ret = -EINVAL;
3091 goto error_open;
3092 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003093
3094 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3095 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3096 ALOGV("read and update_pass through formats");
3097 ret = audio_extn_dolby_update_passt_formats(adev, out);
3098 if(ret != 0) {
3099 goto error_open;
3100 }
3101 if(config->offload_info.format == 0)
3102 config->offload_info.format = out->supported_formats[0];
3103 }
3104
Mingming Yin90310102013-11-13 16:57:00 -08003105 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003106 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003107 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003108 ret = -EINVAL;
3109 goto error_open;
3110 }
3111
3112 out->compr_config.codec = (struct snd_codec *)
3113 calloc(1, sizeof(struct snd_codec));
3114
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003115 if (!out->compr_config.codec) {
3116 ret = -ENOMEM;
3117 goto error_open;
3118 }
3119
vivek mehta0ea887a2015-08-26 14:01:20 -07003120 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003121 out->usecase = get_offload_usecase(adev, true);
3122 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003123 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003124 out->stream.set_callback = out_set_callback;
3125 out->stream.pause = out_pause;
3126 out->stream.resume = out_resume;
3127 out->stream.drain = out_drain;
3128 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003129 out->usecase = get_offload_usecase(adev, false);
3130 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003131 }
vivek mehta446c3962015-09-14 10:57:35 -07003132
3133 if (out->usecase == USECASE_INVALID) {
Alexy Josephb1379942016-01-29 15:49:38 -08003134 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
vivek mehta446c3962015-09-14 10:57:35 -07003135 ret = -EEXIST;
3136 goto error_open;
3137 }
3138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 if (config->offload_info.channel_mask)
3140 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003141 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003142 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003143 config->offload_info.channel_mask = config->channel_mask;
3144 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003145 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 out->sample_rate = config->offload_info.sample_rate;
3147
Mingming Yin3ee55c62014-08-04 14:23:35 -07003148 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003150 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003151 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003152 audio_extn_dolby_get_snd_codec_id(adev, out,
3153 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003154 else
3155 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003156 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003157
3158 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3159 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003160 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003161 platform_get_pcm_offload_buffer_size(&config->offload_info);
3162 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3163 out->compr_config.fragment_size =
3164 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003165 } else {
3166 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003167 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003168 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3170 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003171 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 out->compr_config.codec->bit_rate =
3173 config->offload_info.bit_rate;
3174 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003175 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003176 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303177 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003178 /*TODO: Do we need to change it for passthrough */
3179 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180
Manish Dewangana6fc5442015-08-24 20:30:31 +05303181 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3182 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3183 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3184 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003185 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3186 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003187 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003188 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003189 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3190 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003191
Mingming Yin3ee55c62014-08-04 14:23:35 -07003192 if (out->bit_width == 24) {
3193 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3194 }
3195
Amit Shekhar6f461b12014-08-01 14:52:58 -07003196 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303197 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003198
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3200 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003201
Mingming Yin497419f2015-07-01 16:57:32 -07003202 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003203 //this flag is set from framework only if its for PCM formats
3204 //no need to check for PCM format again
3205 out->non_blocking = 0;
3206 out->use_small_bufs = true;
3207 ALOGI("Keep write blocking for small buff: non_blockling %d",
3208 out->non_blocking);
3209 }
3210
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003211 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303212 out->send_next_track_params = false;
3213 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003214 out->offload_state = OFFLOAD_STATE_IDLE;
3215 out->playback_started = 0;
3216
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003217 audio_extn_dts_create_state_notifier_node(out->usecase);
3218
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219 create_offload_callback_thread(out);
3220 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3221 __func__, config->offload_info.version,
3222 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003223 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003224 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003225 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3226 ret = voice_check_and_set_incall_music_usecase(adev, out);
3227 if (ret != 0) {
3228 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3229 __func__, ret);
3230 goto error_open;
3231 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003232 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3233 if (config->sample_rate == 0)
3234 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3235 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3236 config->sample_rate != 8000) {
3237 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3238 ret = -EINVAL;
3239 goto error_open;
3240 }
3241 out->sample_rate = config->sample_rate;
3242 out->config.rate = config->sample_rate;
3243 if (config->format == AUDIO_FORMAT_DEFAULT)
3244 config->format = AUDIO_FORMAT_PCM_16_BIT;
3245 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3246 config->format = AUDIO_FORMAT_PCM_16_BIT;
3247 ret = -EINVAL;
3248 goto error_open;
3249 }
3250 out->format = config->format;
3251 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3252 out->config = pcm_config_afe_proxy_playback;
3253 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003254 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3255 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3256 out->config = pcm_config_low_latency;
3257 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003258 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003259 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3261 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003263 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3264 format = AUDIO_FORMAT_PCM_16_BIT;
3265 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3266 out->config = pcm_config_deep_buffer;
3267 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003268 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003269 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003270 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003271 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003272 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003273 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 }
3275
Amit Shekhar1d896042014-10-03 13:16:09 -07003276 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3277 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003278 /* TODO remove this hardcoding and check why width is zero*/
3279 if (out->bit_width == 0)
3280 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003281 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3282 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003283 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303284 out->bit_width, out->channel_mask,
3285 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003286 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3287 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3288 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003289 if(adev->primary_output == NULL)
3290 adev->primary_output = out;
3291 else {
3292 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003293 ret = -EEXIST;
3294 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003295 }
3296 }
3297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 /* Check if this usecase is already existing */
3299 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003300 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3301 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003304 ret = -EEXIST;
3305 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 }
3307 pthread_mutex_unlock(&adev->lock);
3308
3309 out->stream.common.get_sample_rate = out_get_sample_rate;
3310 out->stream.common.set_sample_rate = out_set_sample_rate;
3311 out->stream.common.get_buffer_size = out_get_buffer_size;
3312 out->stream.common.get_channels = out_get_channels;
3313 out->stream.common.get_format = out_get_format;
3314 out->stream.common.set_format = out_set_format;
3315 out->stream.common.standby = out_standby;
3316 out->stream.common.dump = out_dump;
3317 out->stream.common.set_parameters = out_set_parameters;
3318 out->stream.common.get_parameters = out_get_parameters;
3319 out->stream.common.add_audio_effect = out_add_audio_effect;
3320 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3321 out->stream.get_latency = out_get_latency;
3322 out->stream.set_volume = out_set_volume;
3323 out->stream.write = out_write;
3324 out->stream.get_render_position = out_get_render_position;
3325 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003326 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003329 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003330 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331
3332 config->format = out->stream.common.get_format(&out->stream.common);
3333 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3334 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3335
3336 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303337 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003338 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003339
3340 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3341 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3342 popcount(out->channel_mask), out->playback_started);
3343
Eric Laurent994a6932013-07-17 11:51:42 -07003344 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003346
3347error_open:
3348 free(out);
3349 *stream_out = NULL;
3350 ALOGD("%s: exit: ret %d", __func__, ret);
3351 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352}
3353
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003354static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 struct audio_stream_out *stream)
3356{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003357 struct stream_out *out = (struct stream_out *)stream;
3358 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003359 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003360
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303361 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3362
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003363 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303364 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003365 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303366 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003367 if(ret != 0)
3368 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3369 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003370 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003371 out_standby(&stream->common);
3372
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003373 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003374 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003376 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003377 if (out->compr_config.codec != NULL)
3378 free(out->compr_config.codec);
3379 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003380
3381 if (adev->voice_tx_output == out)
3382 adev->voice_tx_output = NULL;
3383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384 pthread_cond_destroy(&out->cond);
3385 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003387 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388}
3389
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003390static void close_compress_sessions(struct audio_device *adev)
3391{
Mingming Yin7b762e72015-03-04 13:47:32 -08003392 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303393 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003394 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003395 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303396
3397 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003398 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303399 if (is_offload_usecase(usecase->id)) {
3400 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003401 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3402 out = usecase->stream.out;
3403 pthread_mutex_unlock(&adev->lock);
3404 out_standby(&out->stream.common);
3405 pthread_mutex_lock(&adev->lock);
3406 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303407 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003408 }
3409 pthread_mutex_unlock(&adev->lock);
3410}
3411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3413{
3414 struct audio_device *adev = (struct audio_device *)dev;
3415 struct str_parms *parms;
3416 char *str;
3417 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003418 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003419 int ret;
3420 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003422 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303425 if (!parms)
3426 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003427 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3428 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303429 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303430 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303431 struct listnode *node;
3432 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303433 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303434 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303435 } else if (strstr(snd_card_status, "ONLINE")) {
3436 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303437 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003438 //send dts hpx license if enabled
3439 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303440 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303441 }
3442
3443 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003444 status = voice_set_parameters(adev, parms);
3445 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003446 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003448 status = platform_set_parameters(adev->platform, parms);
3449 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003450 goto done;
3451
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003452 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3453 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003454 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3456 adev->bluetooth_nrec = true;
3457 else
3458 adev->bluetooth_nrec = false;
3459 }
3460
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003461 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3462 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3464 adev->screen_off = false;
3465 else
3466 adev->screen_off = true;
3467 }
3468
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003469 ret = str_parms_get_int(parms, "rotation", &val);
3470 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003471 bool reverse_speakers = false;
3472 switch(val) {
3473 // FIXME: note that the code below assumes that the speakers are in the correct placement
3474 // relative to the user when the device is rotated 90deg from its default rotation. This
3475 // assumption is device-specific, not platform-specific like this code.
3476 case 270:
3477 reverse_speakers = true;
3478 break;
3479 case 0:
3480 case 90:
3481 case 180:
3482 break;
3483 default:
3484 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003485 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003486 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003487 if (status == 0) {
3488 if (adev->speaker_lr_swap != reverse_speakers) {
3489 adev->speaker_lr_swap = reverse_speakers;
3490 // only update the selected device if there is active pcm playback
3491 struct audio_usecase *usecase;
3492 struct listnode *node;
3493 list_for_each(node, &adev->usecase_list) {
3494 usecase = node_to_item(node, struct audio_usecase, list);
3495 if (usecase->type == PCM_PLAYBACK) {
3496 select_devices(adev, usecase->id);
3497 break;
3498 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003499 }
3500 }
3501 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003502 }
3503
Mingming Yin514a8bc2014-07-29 15:22:21 -07003504 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3505 if (ret >= 0) {
3506 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3507 adev->bt_wb_speech_enabled = true;
3508 else
3509 adev->bt_wb_speech_enabled = false;
3510 }
3511
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003512 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3513 if (ret >= 0) {
3514 val = atoi(value);
3515 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3516 ALOGV("cache new edid");
3517 platform_cache_edid(adev->platform);
3518 }
3519 }
3520
3521 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3522 if (ret >= 0) {
3523 val = atoi(value);
3524 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3525 ALOGV("invalidate cached edid");
3526 platform_invalidate_edid(adev->platform);
3527 }
3528 }
3529
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003530 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003531
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003532done:
3533 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003534 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303535error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003536 ALOGV("%s: exit with code(%d)", __func__, status);
3537 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538}
3539
3540static char* adev_get_parameters(const struct audio_hw_device *dev,
3541 const char *keys)
3542{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003543 struct audio_device *adev = (struct audio_device *)dev;
3544 struct str_parms *reply = str_parms_create();
3545 struct str_parms *query = str_parms_create_str(keys);
3546 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303547 char value[256] = {0};
3548 int ret = 0;
3549
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003550 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003551 if (reply) {
3552 str_parms_destroy(reply);
3553 }
3554 if (query) {
3555 str_parms_destroy(query);
3556 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003557 ALOGE("adev_get_parameters: failed to create query or reply");
3558 return NULL;
3559 }
3560
Naresh Tannirud7205b62014-06-20 02:54:48 +05303561 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3562 sizeof(value));
3563 if (ret >=0) {
3564 int val = 1;
3565 pthread_mutex_lock(&adev->snd_card_status.lock);
3566 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3567 val = 0;
3568 pthread_mutex_unlock(&adev->snd_card_status.lock);
3569 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3570 goto exit;
3571 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003572
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003573 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003574 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003575 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003576 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303577 pthread_mutex_unlock(&adev->lock);
3578
Naresh Tannirud7205b62014-06-20 02:54:48 +05303579exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003580 str = str_parms_to_str(reply);
3581 str_parms_destroy(query);
3582 str_parms_destroy(reply);
3583
3584 ALOGV("%s: exit: returns - %s", __func__, str);
3585 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586}
3587
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003588static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589{
3590 return 0;
3591}
3592
3593static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3594{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003595 int ret;
3596 struct audio_device *adev = (struct audio_device *)dev;
3597 pthread_mutex_lock(&adev->lock);
3598 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003599 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003600 pthread_mutex_unlock(&adev->lock);
3601 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602}
3603
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003604static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3605 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606{
3607 return -ENOSYS;
3608}
3609
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003610static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3611 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612{
3613 return -ENOSYS;
3614}
3615
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003616static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3617 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618{
3619 return -ENOSYS;
3620}
3621
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003622static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3623 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624{
3625 return -ENOSYS;
3626}
3627
3628static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3629{
3630 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 pthread_mutex_lock(&adev->lock);
3633 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003634 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08003636 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003637 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003638 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003639 adev->current_call_output = NULL;
3640 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 }
3642 pthread_mutex_unlock(&adev->lock);
3643 return 0;
3644}
3645
3646static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3647{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003648 int ret;
3649
3650 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003651 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003652 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3653 pthread_mutex_unlock(&adev->lock);
3654
3655 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656}
3657
3658static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3659{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003660 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 return 0;
3662}
3663
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003664static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 const struct audio_config *config)
3666{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003667 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003669 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3670 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671}
3672
3673static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003674 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 audio_devices_t devices,
3676 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003677 struct audio_stream_in **stream_in,
3678 audio_input_flags_t flags __unused,
3679 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003680 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681{
3682 struct audio_device *adev = (struct audio_device *)dev;
3683 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003684 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003685 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003686 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 *stream_in = NULL;
3689 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3690 return -EINVAL;
3691
3692 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003693
3694 if (!in) {
3695 ALOGE("failed to allocate input stream");
3696 return -ENOMEM;
3697 }
3698
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303699 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003700 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3701 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003703 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003704 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 in->stream.common.get_sample_rate = in_get_sample_rate;
3707 in->stream.common.set_sample_rate = in_set_sample_rate;
3708 in->stream.common.get_buffer_size = in_get_buffer_size;
3709 in->stream.common.get_channels = in_get_channels;
3710 in->stream.common.get_format = in_get_format;
3711 in->stream.common.set_format = in_set_format;
3712 in->stream.common.standby = in_standby;
3713 in->stream.common.dump = in_dump;
3714 in->stream.common.set_parameters = in_set_parameters;
3715 in->stream.common.get_parameters = in_get_parameters;
3716 in->stream.common.add_audio_effect = in_add_audio_effect;
3717 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3718 in->stream.set_gain = in_set_gain;
3719 in->stream.read = in_read;
3720 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3721
3722 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003723 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 in->standby = 1;
3726 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003727 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003728 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729
3730 /* Update config params with the requested sample rate and channels */
3731 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003732 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3733 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3734 is_low_latency = true;
3735#if LOW_LATENCY_CAPTURE_USE_CASE
3736 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3737#endif
3738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003741 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003743 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303744 if (adev->mode != AUDIO_MODE_IN_CALL) {
3745 ret = -EINVAL;
3746 goto err_open;
3747 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003748 if (config->sample_rate == 0)
3749 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3750 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3751 config->sample_rate != 8000) {
3752 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3753 ret = -EINVAL;
3754 goto err_open;
3755 }
3756 if (config->format == AUDIO_FORMAT_DEFAULT)
3757 config->format = AUDIO_FORMAT_PCM_16_BIT;
3758 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3759 config->format = AUDIO_FORMAT_PCM_16_BIT;
3760 ret = -EINVAL;
3761 goto err_open;
3762 }
3763
3764 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3765 in->config = pcm_config_afe_proxy_record;
3766 in->config.channels = channel_count;
3767 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303768 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3769 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003770 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003771 audio_extn_compr_cap_format_supported(config->format) &&
3772 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003773 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003774 } else {
3775 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003776 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003777 buffer_size = get_input_buffer_size(config->sample_rate,
3778 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003779 channel_count,
3780 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003781 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003782 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3783 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3784 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3785 (in->config.rate == 8000 || in->config.rate == 16000) &&
3786 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3787 voice_extn_compress_voip_open_input_stream(in);
3788 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003789 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003791 /* This stream could be for sound trigger lab,
3792 get sound trigger pcm if present */
3793 audio_extn_sound_trigger_check_and_get_session(in);
3794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003796 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003797 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798
3799err_open:
3800 free(in);
3801 *stream_in = NULL;
3802 return ret;
3803}
3804
3805static void adev_close_input_stream(struct audio_hw_device *dev,
3806 struct audio_stream_in *stream)
3807{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003808 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003809 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003810 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303811
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303812 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003813
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303814 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003815 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303816
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003817 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303818 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003819 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303820 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003821 if (ret != 0)
3822 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3823 __func__, ret);
3824 } else
3825 in_standby(&stream->common);
3826
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003827 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003828 audio_extn_ssr_deinit();
3829 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830
Mingming Yine62d7842013-10-25 16:26:03 -07003831 if(audio_extn_compr_cap_enabled() &&
3832 audio_extn_compr_cap_format_supported(in->config.format))
3833 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003834
3835 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836 return;
3837}
3838
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003839static int adev_dump(const audio_hw_device_t *device __unused,
3840 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841{
3842 return 0;
3843}
3844
3845static int adev_close(hw_device_t *device)
3846{
3847 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003848
3849 if (!adev)
3850 return 0;
3851
3852 pthread_mutex_lock(&adev_init_lock);
3853
3854 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003855 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003856 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003857 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003858 audio_route_free(adev->audio_route);
3859 free(adev->snd_dev_ref_cnt);
3860 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003861 if (adev->adm_deinit)
3862 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003863 free(device);
3864 adev = NULL;
3865 }
3866 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 return 0;
3869}
3870
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003871/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3872 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3873 * just that it _might_ work.
3874 */
3875static int period_size_is_plausible_for_low_latency(int period_size)
3876{
3877 switch (period_size) {
3878 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003879 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003880 case 240:
3881 case 320:
3882 case 480:
3883 return 1;
3884 default:
3885 return 0;
3886 }
3887}
3888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889static int adev_open(const hw_module_t *module, const char *name,
3890 hw_device_t **device)
3891{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003892 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003894 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3896
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003897 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003898 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003899 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003900 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003901 ALOGD("%s: returning existing instance of adev", __func__);
3902 ALOGD("%s: exit", __func__);
3903 pthread_mutex_unlock(&adev_init_lock);
3904 return 0;
3905 }
3906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 adev = calloc(1, sizeof(struct audio_device));
3908
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003909 if (!adev) {
3910 pthread_mutex_unlock(&adev_init_lock);
3911 return -ENOMEM;
3912 }
3913
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003914 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003916 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3917 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3918 adev->device.common.module = (struct hw_module_t *)module;
3919 adev->device.common.close = adev_close;
3920
3921 adev->device.init_check = adev_init_check;
3922 adev->device.set_voice_volume = adev_set_voice_volume;
3923 adev->device.set_master_volume = adev_set_master_volume;
3924 adev->device.get_master_volume = adev_get_master_volume;
3925 adev->device.set_master_mute = adev_set_master_mute;
3926 adev->device.get_master_mute = adev_get_master_mute;
3927 adev->device.set_mode = adev_set_mode;
3928 adev->device.set_mic_mute = adev_set_mic_mute;
3929 adev->device.get_mic_mute = adev_get_mic_mute;
3930 adev->device.set_parameters = adev_set_parameters;
3931 adev->device.get_parameters = adev_get_parameters;
3932 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3933 adev->device.open_output_stream = adev_open_output_stream;
3934 adev->device.close_output_stream = adev_close_output_stream;
3935 adev->device.open_input_stream = adev_open_input_stream;
3936 adev->device.close_input_stream = adev_close_input_stream;
3937 adev->device.dump = adev_dump;
3938
3939 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003940 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003941 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003942 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003945 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003946 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003947 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003948 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003949 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003950 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003951 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303952 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303953 adev->perf_lock_opts[0] = 0x101;
3954 adev->perf_lock_opts[1] = 0x20E;
3955 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303956
3957 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3958 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003960 adev->platform = platform_init(adev);
3961 if (!adev->platform) {
3962 free(adev->snd_dev_ref_cnt);
3963 free(adev);
3964 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3965 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003966 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003967 return -EINVAL;
3968 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003969
Naresh Tanniru4c630392014-05-12 01:05:52 +05303970 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3971
Eric Laurentc4aef752013-09-12 17:45:53 -07003972 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3973 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3974 if (adev->visualizer_lib == NULL) {
3975 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3976 } else {
3977 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3978 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003979 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003980 "visualizer_hal_start_output");
3981 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003982 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003983 "visualizer_hal_stop_output");
3984 }
3985 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003986 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003987 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003988
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003989 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3990 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3991 if (adev->offload_effects_lib == NULL) {
3992 ALOGE("%s: DLOPEN failed for %s", __func__,
3993 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3994 } else {
3995 ALOGV("%s: DLOPEN successful for %s", __func__,
3996 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3997 adev->offload_effects_start_output =
3998 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3999 "offload_effects_bundle_hal_start_output");
4000 adev->offload_effects_stop_output =
4001 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4002 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004003 adev->offload_effects_set_hpx_state =
4004 (int (*)(bool))dlsym(adev->offload_effects_lib,
4005 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304006 adev->offload_effects_get_parameters =
4007 (void (*)(struct str_parms *, struct str_parms *))
4008 dlsym(adev->offload_effects_lib,
4009 "offload_effects_bundle_get_parameters");
4010 adev->offload_effects_set_parameters =
4011 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4012 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004013 }
4014 }
4015
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004016 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4017 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4018 if (adev->adm_lib == NULL) {
4019 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4020 } else {
4021 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4022 adev->adm_init = (adm_init_t)
4023 dlsym(adev->adm_lib, "adm_init");
4024 adev->adm_deinit = (adm_deinit_t)
4025 dlsym(adev->adm_lib, "adm_deinit");
4026 adev->adm_register_input_stream = (adm_register_input_stream_t)
4027 dlsym(adev->adm_lib, "adm_register_input_stream");
4028 adev->adm_register_output_stream = (adm_register_output_stream_t)
4029 dlsym(adev->adm_lib, "adm_register_output_stream");
4030 adev->adm_deregister_stream = (adm_deregister_stream_t)
4031 dlsym(adev->adm_lib, "adm_deregister_stream");
4032 adev->adm_request_focus = (adm_request_focus_t)
4033 dlsym(adev->adm_lib, "adm_request_focus");
4034 adev->adm_abandon_focus = (adm_abandon_focus_t)
4035 dlsym(adev->adm_lib, "adm_abandon_focus");
4036 }
4037 }
4038
Mingming Yin514a8bc2014-07-29 15:22:21 -07004039 adev->bt_wb_speech_enabled = false;
4040
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004041 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042 *device = &adev->device.common;
4043
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004044 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4045 &adev->streams_output_cfg_list);
4046
Kiran Kandi910e1862013-10-29 13:29:42 -07004047 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004048
4049 char value[PROPERTY_VALUE_MAX];
4050 int trial;
4051 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4052 trial = atoi(value);
4053 if (period_size_is_plausible_for_low_latency(trial)) {
4054 pcm_config_low_latency.period_size = trial;
4055 pcm_config_low_latency.start_threshold = trial / 4;
4056 pcm_config_low_latency.avail_min = trial / 4;
4057 configured_low_latency_capture_period_size = trial;
4058 }
4059 }
4060 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4061 trial = atoi(value);
4062 if (period_size_is_plausible_for_low_latency(trial)) {
4063 configured_low_latency_capture_period_size = trial;
4064 }
4065 }
4066
vivek mehta446c3962015-09-14 10:57:35 -07004067 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004068 pthread_mutex_unlock(&adev_init_lock);
4069
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004070 if (adev->adm_init)
4071 adev->adm_data = adev->adm_init();
4072
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304073 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004074 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 return 0;
4076}
4077
4078static struct hw_module_methods_t hal_module_methods = {
4079 .open = adev_open,
4080};
4081
4082struct audio_module HAL_MODULE_INFO_SYM = {
4083 .common = {
4084 .tag = HARDWARE_MODULE_TAG,
4085 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4086 .hal_api_version = HARDWARE_HAL_API_VERSION,
4087 .id = AUDIO_HARDWARE_MODULE_ID,
4088 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004089 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090 .methods = &hal_module_methods,
4091 },
4092};