blob: c088ffd7b9c780bf09ca9b8d42ac4616e20572d7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, 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) &&
757 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700758 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700759 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
760 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700761 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700762 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 switch_device[usecase->id] = true;
764 num_uc_to_switch++;
765 }
766 }
767
768 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700769 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700770
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530771 /* Make sure the previous devices to be disabled first and then enable the
772 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700773 list_for_each(node, &adev->usecase_list) {
774 usecase = node_to_item(node, struct audio_usecase, list);
775 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700776 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800777 }
778 }
779
780 list_for_each(node, &adev->usecase_list) {
781 usecase = node_to_item(node, struct audio_usecase, list);
782 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700783 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700784 }
785 }
786
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 /* Re-route all the usecases on the shared backend other than the
788 specified usecase to new snd devices */
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
791 /* Update the in_snd_device only before enabling the audio route */
792 if (switch_device[usecase->id] ) {
793 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800794 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530795 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700796 }
797 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700798 }
799}
800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800801/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700802static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800803{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700804 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700805 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806
807 switch (channels) {
808 /*
809 * Do not handle stereo output in Multi-channel cases
810 * Stereo case is handled in normal playback path
811 */
812 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700813 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
814 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
815 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
816 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
817 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
818 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819 break;
820 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700821 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
822 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
823 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
824 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
825 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828 break;
829 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700830 ALOGE("HDMI does not support multi channel playback");
831 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800832 break;
833 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700834 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835}
836
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800837audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
838 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700839{
840 struct audio_usecase *usecase;
841 struct listnode *node;
842
843 list_for_each(node, &adev->usecase_list) {
844 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800845 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700846 ALOGV("%s: usecase id %d", __func__, usecase->id);
847 return usecase->id;
848 }
849 }
850 return USECASE_INVALID;
851}
852
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700853struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700854 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855{
856 struct audio_usecase *usecase;
857 struct listnode *node;
858
859 list_for_each(node, &adev->usecase_list) {
860 usecase = node_to_item(node, struct audio_usecase, list);
861 if (usecase->id == uc_id)
862 return usecase;
863 }
864 return NULL;
865}
866
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530867/*
868 * is a true native playback active
869 */
870bool audio_is_true_native_stream_active(struct audio_device *adev)
871{
872 bool active = false;
873 int i = 0;
874 struct listnode *node;
875
876 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
877 ALOGV("%s:napb: not in true mode or non hdphones device",
878 __func__);
879 active = false;
880 goto exit;
881 }
882
883 list_for_each(node, &adev->usecase_list) {
884 struct audio_usecase *uc;
885 uc = node_to_item(node, struct audio_usecase, list);
886 struct stream_out *curr_out =
887 (struct stream_out*) uc->stream.out;
888
889 if (curr_out && PCM_PLAYBACK == uc->type) {
890 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
891 "(%d) device %s", __func__, i++, use_case_table[uc->id],
892 uc->id, curr_out->sample_rate,
893 curr_out->bit_width,
894 platform_get_snd_device_name(uc->out_snd_device));
895
896 if (is_offload_usecase(uc->id) &&
897 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
898 active = true;
899 ALOGD("%s:napb:native stream detected", __func__);
900 }
901 }
902 }
903exit:
904 return active;
905}
906
907
908static bool force_device_switch(struct audio_usecase *usecase)
909{
910 bool ret = false;
911 bool is_it_true_mode = false;
912
913 if (is_offload_usecase(usecase->id) &&
914 (usecase->stream.out) &&
915 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
916 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
917 if ((is_it_true_mode && !adev->native_playback_enabled) ||
918 (!is_it_true_mode && adev->native_playback_enabled)){
919 ret = true;
920 ALOGD("napb: time to toggle native mode");
921 }
922 }
923
924 return ret;
925}
926
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700927int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800929 snd_device_t out_snd_device = SND_DEVICE_NONE;
930 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 struct audio_usecase *usecase = NULL;
932 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800933 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800934 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800935 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800936 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700937 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800938
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530939 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 usecase = get_usecase_from_list(adev, uc_id);
942 if (usecase == NULL) {
943 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
944 return -EINVAL;
945 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800947 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800948 (usecase->type == VOIP_CALL) ||
949 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700950 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800951 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 usecase->devices = usecase->stream.out->devices;
954 } else {
955 /*
956 * If the voice call is active, use the sound devices of voice call usecase
957 * so that it would not result any device switch. All the usecases will
958 * be switched to new device when select_devices() is called for voice call
959 * usecase. This is to avoid switching devices for voice call when
960 * check_usecases_codec_backend() is called below.
961 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700962 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700963 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800964 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700965 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
966 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967 in_snd_device = vc_usecase->in_snd_device;
968 out_snd_device = vc_usecase->out_snd_device;
969 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800970 } else if (voice_extn_compress_voip_is_active(adev)) {
971 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700972 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530973 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700974 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800975 in_snd_device = voip_usecase->in_snd_device;
976 out_snd_device = voip_usecase->out_snd_device;
977 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800978 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800979 hfp_ucid = audio_extn_hfp_get_usecase();
980 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700981 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800982 in_snd_device = hfp_usecase->in_snd_device;
983 out_snd_device = hfp_usecase->out_snd_device;
984 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 }
986 if (usecase->type == PCM_PLAYBACK) {
987 usecase->devices = usecase->stream.out->devices;
988 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700989 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700990 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800991 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700992 if (usecase->stream.out == adev->primary_output &&
993 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800994 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700995 select_devices(adev, adev->active_input->usecase);
996 }
997 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 } else if (usecase->type == PCM_CAPTURE) {
999 usecase->devices = usecase->stream.in->device;
1000 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001001 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001002 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301003 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1004 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1005 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1006 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001007 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001008 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001009 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1010 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001011 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001012 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001013 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001014 }
1015 }
1016
1017 if (out_snd_device == usecase->out_snd_device &&
1018 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301019
1020 if (!force_device_switch(usecase))
1021 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022 }
1023
sangwoobc677242013-08-08 16:53:43 +09001024 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001025 out_snd_device, platform_get_snd_device_name(out_snd_device),
1026 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 /*
1029 * Limitation: While in call, to do a device switch we need to disable
1030 * and enable both RX and TX devices though one of them is same as current
1031 * device.
1032 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001033 if ((usecase->type == VOICE_CALL) &&
1034 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1035 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001036 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001037 }
1038
1039 if (((usecase->type == VOICE_CALL) ||
1040 (usecase->type == VOIP_CALL)) &&
1041 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1042 /* Disable sidetone only if voice/voip call already exists */
1043 if (voice_is_call_state_active(adev) ||
1044 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001045 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001046 }
1047
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048 /* Disable current sound devices */
1049 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001050 disable_audio_route(adev, usecase);
1051 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052 }
1053
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001055 disable_audio_route(adev, usecase);
1056 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057 }
1058
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001059 /* Applicable only on the targets that has external modem.
1060 * New device information should be sent to modem before enabling
1061 * the devices to reduce in-call device switch time.
1062 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001063 if ((usecase->type == VOICE_CALL) &&
1064 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1065 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001066 status = platform_switch_voice_call_enable_device_config(adev->platform,
1067 out_snd_device,
1068 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001069 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001070
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 /* Enable new sound devices */
1072 if (out_snd_device != SND_DEVICE_NONE) {
1073 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1074 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001075 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076 }
1077
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001078 if (in_snd_device != SND_DEVICE_NONE) {
1079 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001080 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001081 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082
Avinash Vaish71a8b972014-07-24 15:36:33 +05301083 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001084 status = platform_switch_voice_call_device_post(adev->platform,
1085 out_snd_device,
1086 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301087 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001088 /* Enable sidetone only if voice/voip call already exists */
1089 if (voice_is_call_state_active(adev) ||
1090 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001091 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301092 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001093
sangwoo170731f2013-06-08 15:36:36 +09001094 usecase->in_snd_device = in_snd_device;
1095 usecase->out_snd_device = out_snd_device;
1096
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301097 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001098 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301099 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001100 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301101 usecase->stream.out->flags,
1102 usecase->stream.out->format,
1103 usecase->stream.out->sample_rate,
1104 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301105 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301106 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001107 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301108 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001109
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001110 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001111
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001112 /* Applicable only on the targets that has external modem.
1113 * Enable device command should be sent to modem only after
1114 * enabling voice call mixer controls
1115 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001116 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001117 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1118 out_snd_device,
1119 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301120 ALOGD("%s: done",__func__);
1121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122 return status;
1123}
1124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125static int stop_input_stream(struct stream_in *in)
1126{
1127 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128 struct audio_usecase *uc_info;
1129 struct audio_device *adev = in->dev;
1130
Eric Laurentc8400632013-02-14 19:04:54 -08001131 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132
Eric Laurent994a6932013-07-17 11:51:42 -07001133 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001135 uc_info = get_usecase_from_list(adev, in->usecase);
1136 if (uc_info == NULL) {
1137 ALOGE("%s: Could not find the usecase (%d) in the list",
1138 __func__, in->usecase);
1139 return -EINVAL;
1140 }
1141
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001142 /* Close in-call recording streams */
1143 voice_check_and_stop_incall_rec_usecase(adev, in);
1144
Eric Laurent150dbfe2013-02-27 14:31:02 -08001145 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001146 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147
1148 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001149 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001151 list_remove(&uc_info->list);
1152 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001153
Eric Laurent994a6932013-07-17 11:51:42 -07001154 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 return ret;
1156}
1157
1158int start_input_stream(struct stream_in *in)
1159{
1160 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001161 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162 struct audio_usecase *uc_info;
1163 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301164 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165
Mingming Yin2664a5b2015-09-03 10:53:11 -07001166 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1167 if (get_usecase_from_list(adev, usecase) == NULL)
1168 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301169 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1170 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001171
Naresh Tanniru80659832014-06-04 18:17:56 +05301172
1173 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301174 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301175 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301176 goto error_config;
1177 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301178
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001179 /* Check if source matches incall recording usecase criteria */
1180 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1181 if (ret)
1182 goto error_config;
1183 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001184 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1185
1186 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1187 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1188 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1189 goto error_config;
1190 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001191
Eric Laurentb23d5282013-05-14 15:27:20 -07001192 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001193 if (in->pcm_device_id < 0) {
1194 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1195 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001196 ret = -EINVAL;
1197 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001198 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001199
1200 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001202
1203 if (!uc_info) {
1204 ret = -ENOMEM;
1205 goto error_config;
1206 }
1207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208 uc_info->id = in->usecase;
1209 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001210 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 uc_info->devices = in->device;
1212 uc_info->in_snd_device = SND_DEVICE_NONE;
1213 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001214
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001215 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301216 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1217 adev->perf_lock_opts,
1218 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220
Eric Laurentc8400632013-02-14 19:04:54 -08001221 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001222 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1223
1224 unsigned int flags = PCM_IN;
1225 unsigned int pcm_open_retry_count = 0;
1226
1227 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1228 flags |= PCM_MMAP | PCM_NOIRQ;
1229 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1230 }
1231
1232 while (1) {
1233 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1234 flags, &in->config);
1235 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1236 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1237 if (in->pcm != NULL) {
1238 pcm_close(in->pcm);
1239 in->pcm = NULL;
1240 }
1241 if (pcm_open_retry_count-- == 0) {
1242 ret = -EIO;
1243 goto error_open;
1244 }
1245 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1246 continue;
1247 }
1248 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001250
1251 ALOGV("%s: pcm_prepare", __func__);
1252 ret = pcm_prepare(in->pcm);
1253 if (ret < 0) {
1254 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1255 pcm_close(in->pcm);
1256 in->pcm = NULL;
1257 goto error_open;
1258 }
1259
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301260 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001261 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001262
Eric Laurentc8400632013-02-14 19:04:54 -08001263 return ret;
1264
1265error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301266 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001268error_config:
1269 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301270 /*
1271 * sleep 50ms to allow sufficient time for kernel
1272 * drivers to recover incases like SSR.
1273 */
1274 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001276
1277 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278}
1279
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001280void lock_input_stream(struct stream_in *in)
1281{
1282 pthread_mutex_lock(&in->pre_lock);
1283 pthread_mutex_lock(&in->lock);
1284 pthread_mutex_unlock(&in->pre_lock);
1285}
1286
1287void lock_output_stream(struct stream_out *out)
1288{
1289 pthread_mutex_lock(&out->pre_lock);
1290 pthread_mutex_lock(&out->lock);
1291 pthread_mutex_unlock(&out->pre_lock);
1292}
1293
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001294/* must be called with out->lock locked */
1295static int send_offload_cmd_l(struct stream_out* out, int command)
1296{
1297 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1298
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001299 if (!cmd) {
1300 ALOGE("failed to allocate mem for command 0x%x", command);
1301 return -ENOMEM;
1302 }
1303
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 ALOGVV("%s %d", __func__, command);
1305
1306 cmd->cmd = command;
1307 list_add_tail(&out->offload_cmd_list, &cmd->node);
1308 pthread_cond_signal(&out->offload_cond);
1309 return 0;
1310}
1311
1312/* must be called iwth out->lock locked */
1313static void stop_compressed_output_l(struct stream_out *out)
1314{
1315 out->offload_state = OFFLOAD_STATE_IDLE;
1316 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001317 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 if (out->compr != NULL) {
1319 compress_stop(out->compr);
1320 while (out->offload_thread_blocked) {
1321 pthread_cond_wait(&out->cond, &out->lock);
1322 }
1323 }
1324}
1325
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001326bool is_offload_usecase(audio_usecase_t uc_id)
1327{
1328 unsigned int i;
1329 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1330 if (uc_id == offload_usecases[i])
1331 return true;
1332 }
1333 return false;
1334}
1335
vivek mehta446c3962015-09-14 10:57:35 -07001336static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001337{
vivek mehta446c3962015-09-14 10:57:35 -07001338 audio_usecase_t ret_uc = USECASE_INVALID;
1339 unsigned int offload_uc_index;
1340 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1341 if (!adev->multi_offload_enable) {
1342 if (is_direct_pcm)
1343 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1344 else
1345 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001346
vivek mehta446c3962015-09-14 10:57:35 -07001347 pthread_mutex_lock(&adev->lock);
1348 if (get_usecase_from_list(adev, ret_uc) != NULL)
1349 ret_uc = USECASE_INVALID;
1350 pthread_mutex_unlock(&adev->lock);
1351
1352 return ret_uc;
1353 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001354
1355 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001356 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1357 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1358 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1359 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001360 break;
1361 }
1362 }
vivek mehta446c3962015-09-14 10:57:35 -07001363
1364 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1365 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001366}
1367
1368static void free_offload_usecase(struct audio_device *adev,
1369 audio_usecase_t uc_id)
1370{
vivek mehta446c3962015-09-14 10:57:35 -07001371 unsigned int offload_uc_index;
1372 int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1373
1374 if (!adev->multi_offload_enable)
1375 return;
1376
1377 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1378 if (offload_usecases[offload_uc_index] == uc_id) {
1379 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001380 break;
1381 }
1382 }
1383 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1384}
1385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001386static void *offload_thread_loop(void *context)
1387{
1388 struct stream_out *out = (struct stream_out *) context;
1389 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001390 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1393 set_sched_policy(0, SP_FOREGROUND);
1394 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1395
1396 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001397 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001398 for (;;) {
1399 struct offload_cmd *cmd = NULL;
1400 stream_callback_event_t event;
1401 bool send_callback = false;
1402
1403 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1404 __func__, list_empty(&out->offload_cmd_list),
1405 out->offload_state);
1406 if (list_empty(&out->offload_cmd_list)) {
1407 ALOGV("%s SLEEPING", __func__);
1408 pthread_cond_wait(&out->offload_cond, &out->lock);
1409 ALOGV("%s RUNNING", __func__);
1410 continue;
1411 }
1412
1413 item = list_head(&out->offload_cmd_list);
1414 cmd = node_to_item(item, struct offload_cmd, node);
1415 list_remove(item);
1416
1417 ALOGVV("%s STATE %d CMD %d out->compr %p",
1418 __func__, out->offload_state, cmd->cmd, out->compr);
1419
1420 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1421 free(cmd);
1422 break;
1423 }
1424
1425 if (out->compr == NULL) {
1426 ALOGE("%s: Compress handle is NULL", __func__);
1427 pthread_cond_signal(&out->cond);
1428 continue;
1429 }
1430 out->offload_thread_blocked = true;
1431 pthread_mutex_unlock(&out->lock);
1432 send_callback = false;
1433 switch(cmd->cmd) {
1434 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001435 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001436 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001437 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001438 send_callback = true;
1439 event = STREAM_CBK_EVENT_WRITE_READY;
1440 break;
1441 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001442 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301443 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001444 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301445 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001446 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301447 if (ret < 0)
1448 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301449 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301450 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001451 compress_drain(out->compr);
1452 else
1453 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301454 if (ret != -ENETRESET) {
1455 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301456 pthread_mutex_lock(&out->lock);
1457 out->send_new_metadata = 1;
1458 out->send_next_track_params = true;
1459 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301460 event = STREAM_CBK_EVENT_DRAIN_READY;
1461 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1462 } else
1463 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001464 break;
1465 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001466 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001467 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001468 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001469 send_callback = true;
1470 event = STREAM_CBK_EVENT_DRAIN_READY;
1471 break;
1472 default:
1473 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1474 break;
1475 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001476 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001477 out->offload_thread_blocked = false;
1478 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001479 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001480 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001482 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001483 free(cmd);
1484 }
1485
1486 pthread_cond_signal(&out->cond);
1487 while (!list_empty(&out->offload_cmd_list)) {
1488 item = list_head(&out->offload_cmd_list);
1489 list_remove(item);
1490 free(node_to_item(item, struct offload_cmd, node));
1491 }
1492 pthread_mutex_unlock(&out->lock);
1493
1494 return NULL;
1495}
1496
1497static int create_offload_callback_thread(struct stream_out *out)
1498{
1499 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1500 list_init(&out->offload_cmd_list);
1501 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1502 offload_thread_loop, out);
1503 return 0;
1504}
1505
1506static int destroy_offload_callback_thread(struct stream_out *out)
1507{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001508 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001509 stop_compressed_output_l(out);
1510 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1511
1512 pthread_mutex_unlock(&out->lock);
1513 pthread_join(out->offload_thread, (void **) NULL);
1514 pthread_cond_destroy(&out->offload_cond);
1515
1516 return 0;
1517}
1518
Eric Laurent07eeafd2013-10-06 12:52:49 -07001519static bool allow_hdmi_channel_config(struct audio_device *adev)
1520{
1521 struct listnode *node;
1522 struct audio_usecase *usecase;
1523 bool ret = true;
1524
1525 list_for_each(node, &adev->usecase_list) {
1526 usecase = node_to_item(node, struct audio_usecase, list);
1527 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1528 /*
1529 * If voice call is already existing, do not proceed further to avoid
1530 * disabling/enabling both RX and TX devices, CSD calls, etc.
1531 * Once the voice call done, the HDMI channels can be configured to
1532 * max channels of remaining use cases.
1533 */
1534 if (usecase->id == USECASE_VOICE_CALL) {
1535 ALOGD("%s: voice call is active, no change in HDMI channels",
1536 __func__);
1537 ret = false;
1538 break;
1539 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1540 ALOGD("%s: multi channel playback is active, "
1541 "no change in HDMI channels", __func__);
1542 ret = false;
1543 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001544 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001545 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001546 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1547 ", no change in HDMI channels", __func__,
1548 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001549 ret = false;
1550 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001551 }
1552 }
1553 }
1554 return ret;
1555}
1556
1557static int check_and_set_hdmi_channels(struct audio_device *adev,
1558 unsigned int channels)
1559{
1560 struct listnode *node;
1561 struct audio_usecase *usecase;
1562
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001563 unsigned int supported_channels = platform_edid_get_max_channels(
1564 adev->platform);
1565 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001566 /* Check if change in HDMI channel config is allowed */
1567 if (!allow_hdmi_channel_config(adev))
1568 return 0;
1569
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001570 if (channels > supported_channels)
1571 channels = supported_channels;
1572
Eric Laurent07eeafd2013-10-06 12:52:49 -07001573 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001574 ALOGD("%s: Requested channels are same as current channels(%d)",
1575 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001576 return 0;
1577 }
1578
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001579 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001580 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001581 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001582 adev->cur_hdmi_channels = channels;
1583
1584 /*
1585 * Deroute all the playback streams routed to HDMI so that
1586 * the back end is deactivated. Note that backend will not
1587 * be deactivated if any one stream is connected to it.
1588 */
1589 list_for_each(node, &adev->usecase_list) {
1590 usecase = node_to_item(node, struct audio_usecase, list);
1591 if (usecase->type == PCM_PLAYBACK &&
1592 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001593 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001594 }
1595 }
1596
1597 /*
1598 * Enable all the streams disabled above. Now the HDMI backend
1599 * will be activated with new channel configuration
1600 */
1601 list_for_each(node, &adev->usecase_list) {
1602 usecase = node_to_item(node, struct audio_usecase, list);
1603 if (usecase->type == PCM_PLAYBACK &&
1604 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001605 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001606 }
1607 }
1608
1609 return 0;
1610}
1611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612static int stop_output_stream(struct stream_out *out)
1613{
1614 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 struct audio_usecase *uc_info;
1616 struct audio_device *adev = out->dev;
1617
Eric Laurent994a6932013-07-17 11:51:42 -07001618 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 uc_info = get_usecase_from_list(adev, out->usecase);
1621 if (uc_info == NULL) {
1622 ALOGE("%s: Could not find the usecase (%d) in the list",
1623 __func__, out->usecase);
1624 return -EINVAL;
1625 }
1626
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001627 if (is_offload_usecase(out->usecase) &&
1628 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001629 if (adev->visualizer_stop_output != NULL)
1630 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001631
1632 audio_extn_dts_remove_state_notifier_node(out->usecase);
1633
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001634 if (adev->offload_effects_stop_output != NULL)
1635 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1636 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001637
Eric Laurent150dbfe2013-02-27 14:31:02 -08001638 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001639 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001640
1641 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001642 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001644 list_remove(&uc_info->list);
1645 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001647 if (is_offload_usecase(out->usecase) &&
1648 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1649 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1650 ALOGV("Disable passthrough , reset mixer to pcm");
1651 /* NO_PASSTHROUGH */
1652 out->compr_config.codec->compr_passthr = 0;
1653 audio_extn_dolby_set_hdmi_config(adev, out);
1654 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1655 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656 /* Must be called after removing the usecase from list */
1657 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1658 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1659
Eric Laurent994a6932013-07-17 11:51:42 -07001660 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 return ret;
1662}
1663
1664int start_output_stream(struct stream_out *out)
1665{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001667 int sink_channels = 0;
1668 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669 struct audio_usecase *uc_info;
1670 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301671 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001673 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1674 ret = -EINVAL;
1675 goto error_config;
1676 }
1677
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301678 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1679 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1680 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301681
Naresh Tanniru80659832014-06-04 18:17:56 +05301682 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301683 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301684 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301685 goto error_config;
1686 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301687
Eric Laurentb23d5282013-05-14 15:27:20 -07001688 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689 if (out->pcm_device_id < 0) {
1690 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1691 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001692 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001693 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694 }
1695
1696 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001697
1698 if (!uc_info) {
1699 ret = -ENOMEM;
1700 goto error_config;
1701 }
1702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 uc_info->id = out->usecase;
1704 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001705 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001706 uc_info->devices = out->devices;
1707 uc_info->in_snd_device = SND_DEVICE_NONE;
1708 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001709 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001710 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001711 if (is_offload_usecase(out->usecase)) {
1712 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001713 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1714 }
1715 }
Mingming Yin9c041392014-05-01 15:37:31 -07001716 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1717 if (!strncmp("true", prop_value, 4)) {
1718 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001719 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1720 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001721 check_and_set_hdmi_channels(adev, sink_channels);
1722 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001723 if (is_offload_usecase(out->usecase)) {
1724 unsigned int ch_count = out->compr_config.codec->ch_in;
1725 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1726 /* backend channel config for passthrough stream is stereo */
1727 ch_count = 2;
1728 check_and_set_hdmi_channels(adev, ch_count);
1729 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001730 check_and_set_hdmi_channels(adev, out->config.channels);
1731 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001732 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001733 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001734 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301736 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1737 adev->perf_lock_opts,
1738 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001739 select_devices(adev, out->usecase);
1740
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001741 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1742 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001743 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001744 unsigned int flags = PCM_OUT;
1745 unsigned int pcm_open_retry_count = 0;
1746 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1747 flags |= PCM_MMAP | PCM_NOIRQ;
1748 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1749 } else
1750 flags |= PCM_MONOTONIC;
1751
1752 while (1) {
1753 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1754 flags, &out->config);
1755 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1756 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1757 if (out->pcm != NULL) {
1758 pcm_close(out->pcm);
1759 out->pcm = NULL;
1760 }
1761 if (pcm_open_retry_count-- == 0) {
1762 ret = -EIO;
1763 goto error_open;
1764 }
1765 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1766 continue;
1767 }
1768 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001769 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001770
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001771 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1772 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001773
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001774 ALOGV("%s: pcm_prepare", __func__);
1775 if (pcm_is_ready(out->pcm)) {
1776 ret = pcm_prepare(out->pcm);
1777 if (ret < 0) {
1778 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1779 pcm_close(out->pcm);
1780 out->pcm = NULL;
1781 goto error_open;
1782 }
1783 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001785 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1786 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001788 out->compr = compress_open(adev->snd_card,
1789 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001790 COMPRESS_IN, &out->compr_config);
1791 if (out->compr && !is_compress_ready(out->compr)) {
1792 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1793 compress_close(out->compr);
1794 out->compr = NULL;
1795 ret = -EIO;
1796 goto error_open;
1797 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301798 /* compress_open sends params of the track, so reset the flag here */
1799 out->is_compr_metadata_avail = false;
1800
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001801 if (out->offload_callback)
1802 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001803
Fred Oh3f43e742015-03-04 18:42:34 -08001804 /* Since small bufs uses blocking writes, a write will be blocked
1805 for the default max poll time (20s) in the event of an SSR.
1806 Reduce the poll time to observe and deal with SSR faster.
1807 */
1808 if (out->use_small_bufs) {
1809 compress_set_max_poll_wait(out->compr, 1000);
1810 }
1811
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001812 audio_extn_dts_create_state_notifier_node(out->usecase);
1813 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1814 popcount(out->channel_mask),
1815 out->playback_started);
1816
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001817#ifdef DS1_DOLBY_DDP_ENABLED
1818 if (audio_extn_is_dolby_format(out->format))
1819 audio_extn_dolby_send_ddp_endp_params(adev);
1820#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001821 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1822 if (adev->visualizer_start_output != NULL)
1823 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1824 if (adev->offload_effects_start_output != NULL)
1825 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001826 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001827 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301829 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001830 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001833error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301834 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001836error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301837 /*
1838 * sleep 50ms to allow sufficient time for kernel
1839 * drivers to recover incases like SSR.
1840 */
1841 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001842 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843}
1844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845static int check_input_parameters(uint32_t sample_rate,
1846 audio_format_t format,
1847 int channel_count)
1848{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001849 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001851 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001852 !voice_extn_compress_voip_is_format_supported(format) &&
1853 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001854
1855 switch (channel_count) {
1856 case 1:
1857 case 2:
1858 case 6:
1859 break;
1860 default:
1861 ret = -EINVAL;
1862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863
1864 switch (sample_rate) {
1865 case 8000:
1866 case 11025:
1867 case 12000:
1868 case 16000:
1869 case 22050:
1870 case 24000:
1871 case 32000:
1872 case 44100:
1873 case 48000:
1874 break;
1875 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001876 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 }
1878
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001879 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880}
1881
1882static size_t get_input_buffer_size(uint32_t sample_rate,
1883 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001884 int channel_count,
1885 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886{
1887 size_t size = 0;
1888
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001889 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1890 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001892 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001893 if (is_low_latency)
1894 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001895 /* ToDo: should use frame_size computed based on the format and
1896 channel_count here. */
1897 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001899 /* make sure the size is multiple of 32 bytes
1900 * At 48 kHz mono 16-bit PCM:
1901 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1902 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1903 */
1904 size += 0x1f;
1905 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001906
1907 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908}
1909
1910static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1911{
1912 struct stream_out *out = (struct stream_out *)stream;
1913
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001914 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915}
1916
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001917static int out_set_sample_rate(struct audio_stream *stream __unused,
1918 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919{
1920 return -ENOSYS;
1921}
1922
1923static size_t out_get_buffer_size(const struct audio_stream *stream)
1924{
1925 struct stream_out *out = (struct stream_out *)stream;
1926
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001927 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001928 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001929 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1930 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001932 return out->config.period_size *
1933 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934}
1935
1936static uint32_t out_get_channels(const struct audio_stream *stream)
1937{
1938 struct stream_out *out = (struct stream_out *)stream;
1939
1940 return out->channel_mask;
1941}
1942
1943static audio_format_t out_get_format(const struct audio_stream *stream)
1944{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945 struct stream_out *out = (struct stream_out *)stream;
1946
1947 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948}
1949
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001950static int out_set_format(struct audio_stream *stream __unused,
1951 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952{
1953 return -ENOSYS;
1954}
1955
1956static int out_standby(struct audio_stream *stream)
1957{
1958 struct stream_out *out = (struct stream_out *)stream;
1959 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001960
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301961 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1962 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001963 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1964 /* Ignore standby in case of voip call because the voip output
1965 * stream is closed in adev_close_output_stream()
1966 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301967 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001968 return 0;
1969 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001971 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001973 if (adev->adm_deregister_stream)
1974 adev->adm_deregister_stream(adev->adm_data, out->handle);
1975
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001976 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001978 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001979 if (out->pcm) {
1980 pcm_close(out->pcm);
1981 out->pcm = NULL;
1982 }
1983 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001984 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301986 out->send_next_track_params = false;
1987 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001988 out->gapless_mdata.encoder_delay = 0;
1989 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 if (out->compr != NULL) {
1991 compress_close(out->compr);
1992 out->compr = NULL;
1993 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001996 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 }
1998 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001999 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 return 0;
2001}
2002
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002003static int out_dump(const struct audio_stream *stream __unused,
2004 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005{
2006 return 0;
2007}
2008
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002009static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2010{
2011 int ret = 0;
2012 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002013
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002014 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002015 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002016 return -EINVAL;
2017 }
2018
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302019 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002020
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002021 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2022 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302023 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002024 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002025 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2026 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302027 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002028 }
2029
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002030 ALOGV("%s new encoder delay %u and padding %u", __func__,
2031 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2032
2033 return 0;
2034}
2035
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002036static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2037{
2038 return out == adev->primary_output || out == adev->voice_tx_output;
2039}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2042{
2043 struct stream_out *out = (struct stream_out *)stream;
2044 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002045 struct audio_usecase *usecase;
2046 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 struct str_parms *parms;
2048 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002049 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002050 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
sangwoobc677242013-08-08 16:53:43 +09002052 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002053 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302055 if (!parms)
2056 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002057 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2058 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002060 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002061 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002063 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302064 * When HDMI cable is unplugged/usb hs is disconnected the
2065 * music playback is paused and the policy manager sends routing=0
2066 * But the audioflingercontinues to write data until standby time
2067 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 * Avoid this by routing audio to speaker until standby.
2069 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05302070 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2071 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002072 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08002073 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
2074 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002075 }
2076
2077 /*
2078 * select_devices() call below switches all the usecases on the same
2079 * backend to the new device. Refer to check_usecases_codec_backend() in
2080 * the select_devices(). But how do we undo this?
2081 *
2082 * For example, music playback is active on headset (deep-buffer usecase)
2083 * and if we go to ringtones and select a ringtone, low-latency usecase
2084 * will be started on headset+speaker. As we can't enable headset+speaker
2085 * and headset devices at the same time, select_devices() switches the music
2086 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2087 * So when the ringtone playback is completed, how do we undo the same?
2088 *
2089 * We are relying on the out_set_parameters() call on deep-buffer output,
2090 * once the ringtone playback is ended.
2091 * NOTE: We should not check if the current devices are same as new devices.
2092 * Because select_devices() must be called to switch back the music
2093 * playback to headset.
2094 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002095 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002096 out->devices = val;
2097
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302098 if (!out->standby) {
2099 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2100 adev->perf_lock_opts,
2101 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002102 select_devices(adev, out->usecase);
Sudheer Papothi2db15e02015-10-24 03:26:38 +05302103 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2104 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002105
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002106 if (output_drives_call(adev, out)) {
2107 if(!voice_is_in_call(adev)) {
2108 if (adev->mode == AUDIO_MODE_IN_CALL) {
2109 adev->current_call_output = out;
2110 ret = voice_start_call(adev);
2111 }
2112 } else {
2113 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002114 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002115 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002116 }
2117 }
2118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002120 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002122
2123 if (out == adev->primary_output) {
2124 pthread_mutex_lock(&adev->lock);
2125 audio_extn_set_parameters(adev, parms);
2126 pthread_mutex_unlock(&adev->lock);
2127 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002128 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002129 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002130 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002131
2132 audio_extn_dts_create_state_notifier_node(out->usecase);
2133 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2134 popcount(out->channel_mask),
2135 out->playback_started);
2136
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002137 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002138 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302141error:
Eric Laurent994a6932013-07-17 11:51:42 -07002142 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 return ret;
2144}
2145
2146static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2147{
2148 struct stream_out *out = (struct stream_out *)stream;
2149 struct str_parms *query = str_parms_create_str(keys);
2150 char *str;
2151 char value[256];
2152 struct str_parms *reply = str_parms_create();
2153 size_t i, j;
2154 int ret;
2155 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002156
2157 if (!query || !reply) {
2158 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2159 return NULL;
2160 }
2161
Eric Laurent994a6932013-07-17 11:51:42 -07002162 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2164 if (ret >= 0) {
2165 value[0] = '\0';
2166 i = 0;
2167 while (out->supported_channel_masks[i] != 0) {
2168 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2169 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2170 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002171 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002173 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 first = false;
2175 break;
2176 }
2177 }
2178 i++;
2179 }
2180 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2181 str = str_parms_to_str(reply);
2182 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002183 voice_extn_out_get_parameters(out, query, reply);
2184 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002185 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002186 free(str);
2187 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002188 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002190
Alexy Joseph62142aa2015-11-16 15:10:34 -08002191
2192 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2193 if (ret >= 0) {
2194 value[0] = '\0';
2195 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2196 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302197 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002198 } else {
2199 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302200 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002201 }
2202 str_parms_add_str(reply, "is_direct_pcm_track", value);
2203 str = str_parms_to_str(reply);
2204 }
2205
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002206 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2207 if (ret >= 0) {
2208 value[0] = '\0';
2209 i = 0;
2210 first = true;
2211 while (out->supported_formats[i] != 0) {
2212 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2213 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2214 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002215 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002216 }
2217 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2218 first = false;
2219 break;
2220 }
2221 }
2222 i++;
2223 }
2224 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2225 str = str_parms_to_str(reply);
2226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 str_parms_destroy(query);
2228 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002229 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 return str;
2231}
2232
2233static uint32_t out_get_latency(const struct audio_stream_out *stream)
2234{
2235 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002236 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237
Alexy Josephaa54c872014-12-03 02:46:47 -08002238 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002239 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002240 } else {
2241 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002243 }
2244
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302245 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002246 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247}
2248
2249static int out_set_volume(struct audio_stream_out *stream, float left,
2250 float right)
2251{
Eric Laurenta9024de2013-04-04 09:19:12 -07002252 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002253 int volume[2];
2254
Eric Laurenta9024de2013-04-04 09:19:12 -07002255 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2256 /* only take left channel into account: the API is for stereo anyway */
2257 out->muted = (left == 0.0f);
2258 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002259 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002260 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2261 /*
2262 * Set mute or umute on HDMI passthrough stream.
2263 * Only take left channel into account.
2264 * Mute is 0 and unmute 1
2265 */
2266 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2267 } else {
2268 char mixer_ctl_name[128];
2269 struct audio_device *adev = out->dev;
2270 struct mixer_ctl *ctl;
2271 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002272 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002273
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002274 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2275 "Compress Playback %d Volume", pcm_device_id);
2276 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2277 if (!ctl) {
2278 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2279 __func__, mixer_ctl_name);
2280 return -EINVAL;
2281 }
2282 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2283 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2284 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2285 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002287 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289 return -ENOSYS;
2290}
2291
2292static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2293 size_t bytes)
2294{
2295 struct stream_out *out = (struct stream_out *)stream;
2296 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302297 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002298 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002300 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302301
Naresh Tanniru80659832014-06-04 18:17:56 +05302302 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002303 // increase written size during SSR to avoid mismatch
2304 // with the written frames count in AF
2305 if (!is_offload_usecase(out->usecase))
2306 out->written += bytes / (out->config.channels * sizeof(short));
2307
Naresh Tanniru80659832014-06-04 18:17:56 +05302308 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302309 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302310 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302311 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002312 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302313 //during SSR for compress usecase we should return error to flinger
2314 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2315 pthread_mutex_unlock(&out->lock);
2316 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302317 }
2318 }
2319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002321 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002322 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002323 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2324 ret = voice_extn_compress_voip_start_output_stream(out);
2325 else
2326 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002327 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002328 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002330 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 goto exit;
2332 }
vivek mehta446c3962015-09-14 10:57:35 -07002333 if (!is_offload_usecase(out->usecase) && adev->adm_register_output_stream)
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002334 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336
Ashish Jain81eb2a82015-05-13 10:52:34 +05302337 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2338 audio_utils_set_hdmi_channel_status(out, buffer, bytes);
2339 adev->is_channel_status_set = true;
2340 }
2341
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002342 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002343 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002344 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002345 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002346 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2347 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302348 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2349 ALOGD("copl(%p):send next track params in gapless", out);
2350 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2351 out->send_next_track_params = false;
2352 out->is_compr_metadata_avail = false;
2353 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002354 }
2355
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302357 if (ret < 0)
2358 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002359 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002360 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302361 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302363 } else if (-ENETRESET == ret) {
2364 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2365 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2366 pthread_mutex_unlock(&out->lock);
2367 out_standby(&out->stream.common);
2368 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302370 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002372 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 out->playback_started = 1;
2374 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002375
2376 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2377 popcount(out->channel_mask),
2378 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 }
2380 pthread_mutex_unlock(&out->lock);
2381 return ret;
2382 } else {
2383 if (out->pcm) {
2384 if (out->muted)
2385 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002388
2389 if (adev->adm_request_focus)
2390 adev->adm_request_focus(adev->adm_data, out->handle);
2391
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002392 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2393 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2394 else
2395 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002396
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302397 if (ret < 0)
2398 ret = -errno;
2399 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002400 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002401
2402 if (adev->adm_abandon_focus)
2403 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405 }
2406
2407exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302408 /* ToDo: There may be a corner case when SSR happens back to back during
2409 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302410 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302411 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302412 }
2413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 pthread_mutex_unlock(&out->lock);
2415
2416 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002417 if (out->pcm)
vivek mehtaa76401a2015-04-24 14:12:15 -07002418 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302419 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302420 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302421 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302422 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302423 out->standby = true;
2424 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002426 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302427 out_get_sample_rate(&out->stream.common));
2428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429 }
2430 return bytes;
2431}
2432
2433static int out_get_render_position(const struct audio_stream_out *stream,
2434 uint32_t *dsp_frames)
2435{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302437 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002438
2439 if (dsp_frames == NULL)
2440 return -EINVAL;
2441
2442 *dsp_frames = 0;
2443 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002444 ssize_t ret = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002445 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002446 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302447 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002448 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302449 if (ret < 0)
2450 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 ALOGVV("%s rendered frames %d sample_rate %d",
2452 __func__, *dsp_frames, out->sample_rate);
2453 }
2454 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302455 if (-ENETRESET == ret) {
2456 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2457 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2458 return -EINVAL;
2459 } else if(ret < 0) {
2460 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2461 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302462 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2463 /*
2464 * Handle corner case where compress session is closed during SSR
2465 * and timestamp is queried
2466 */
2467 ALOGE(" ERROR: sound card not active, return error");
2468 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302469 } else {
2470 return 0;
2471 }
Zhou Song32a556e2015-05-05 10:46:56 +08002472 } else if (audio_is_linear_pcm(out->format)) {
2473 *dsp_frames = out->written;
2474 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002475 } else
2476 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477}
2478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002479static int out_add_audio_effect(const struct audio_stream *stream __unused,
2480 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481{
2482 return 0;
2483}
2484
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002485static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2486 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487{
2488 return 0;
2489}
2490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002491static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2492 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493{
2494 return -EINVAL;
2495}
2496
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002497static int out_get_presentation_position(const struct audio_stream_out *stream,
2498 uint64_t *frames, struct timespec *timestamp)
2499{
2500 struct stream_out *out = (struct stream_out *)stream;
2501 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002502 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002503
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002504 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002505
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002506 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002507 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302508 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002509 &out->sample_rate);
2510 ALOGVV("%s rendered frames %ld sample_rate %d",
2511 __func__, dsp_frames, out->sample_rate);
2512 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302513 if (ret < 0)
2514 ret = -errno;
2515 if (-ENETRESET == ret) {
2516 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2517 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2518 ret = -EINVAL;
2519 } else
2520 ret = 0;
2521
Eric Laurent949a0892013-09-20 09:20:13 -07002522 /* this is the best we can do */
2523 clock_gettime(CLOCK_MONOTONIC, timestamp);
2524 }
2525 } else {
2526 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002527 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002528 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2529 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002530 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002531 // This adjustment accounts for buffering after app processor.
2532 // It is based on estimated DSP latency per use case, rather than exact.
2533 signed_frames -=
2534 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2535
Eric Laurent949a0892013-09-20 09:20:13 -07002536 // It would be unusual for this value to be negative, but check just in case ...
2537 if (signed_frames >= 0) {
2538 *frames = signed_frames;
2539 ret = 0;
2540 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002541 }
2542 }
2543 }
2544
2545 pthread_mutex_unlock(&out->lock);
2546
2547 return ret;
2548}
2549
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002550static int out_set_callback(struct audio_stream_out *stream,
2551 stream_callback_t callback, void *cookie)
2552{
2553 struct stream_out *out = (struct stream_out *)stream;
2554
2555 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002556 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002557 out->offload_callback = callback;
2558 out->offload_cookie = cookie;
2559 pthread_mutex_unlock(&out->lock);
2560 return 0;
2561}
2562
2563static int out_pause(struct audio_stream_out* stream)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566 int status = -ENOSYS;
2567 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002568 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002569 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002570 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002571 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302572 struct audio_device *adev = out->dev;
2573 int snd_scard_state = get_snd_card_state(adev);
2574
2575 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2576 status = compress_pause(out->compr);
2577
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002578 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002579
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302580 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002581 audio_extn_dts_notify_playback_state(out->usecase, 0,
2582 out->sample_rate, popcount(out->channel_mask),
2583 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 }
2585 pthread_mutex_unlock(&out->lock);
2586 }
2587 return status;
2588}
2589
2590static int out_resume(struct audio_stream_out* stream)
2591{
2592 struct stream_out *out = (struct stream_out *)stream;
2593 int status = -ENOSYS;
2594 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002595 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002596 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002597 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002598 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002599 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302600 struct audio_device *adev = out->dev;
2601 int snd_scard_state = get_snd_card_state(adev);
2602
2603 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2604 status = compress_resume(out->compr);
2605
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002606 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002607
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302608 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002609 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2610 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611 }
2612 pthread_mutex_unlock(&out->lock);
2613 }
2614 return status;
2615}
2616
2617static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2618{
2619 struct stream_out *out = (struct stream_out *)stream;
2620 int status = -ENOSYS;
2621 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002622 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002623 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2625 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2626 else
2627 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2628 pthread_mutex_unlock(&out->lock);
2629 }
2630 return status;
2631}
2632
2633static int out_flush(struct audio_stream_out* stream)
2634{
2635 struct stream_out *out = (struct stream_out *)stream;
2636 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002637 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002638 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002639 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002640 stop_compressed_output_l(out);
2641 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002642 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002643 return 0;
2644 }
2645 return -ENOSYS;
2646}
2647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648/** audio_stream_in implementation **/
2649static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2650{
2651 struct stream_in *in = (struct stream_in *)stream;
2652
2653 return in->config.rate;
2654}
2655
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002656static int in_set_sample_rate(struct audio_stream *stream __unused,
2657 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658{
2659 return -ENOSYS;
2660}
2661
2662static size_t in_get_buffer_size(const struct audio_stream *stream)
2663{
2664 struct stream_in *in = (struct stream_in *)stream;
2665
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002666 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2667 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002668 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2669 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002670
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002671 return in->config.period_size *
2672 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673}
2674
2675static uint32_t in_get_channels(const struct audio_stream *stream)
2676{
2677 struct stream_in *in = (struct stream_in *)stream;
2678
2679 return in->channel_mask;
2680}
2681
2682static audio_format_t in_get_format(const struct audio_stream *stream)
2683{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002684 struct stream_in *in = (struct stream_in *)stream;
2685
2686 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687}
2688
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002689static int in_set_format(struct audio_stream *stream __unused,
2690 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691{
2692 return -ENOSYS;
2693}
2694
2695static int in_standby(struct audio_stream *stream)
2696{
2697 struct stream_in *in = (struct stream_in *)stream;
2698 struct audio_device *adev = in->dev;
2699 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302700 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2701 stream, in->usecase, use_case_table[in->usecase]);
2702
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002703 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2704 /* Ignore standby in case of voip call because the voip input
2705 * stream is closed in adev_close_input_stream()
2706 */
2707 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2708 return status;
2709 }
2710
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002711 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002712 if (!in->standby && in->is_st_session) {
2713 ALOGD("%s: sound trigger pcm stop lab", __func__);
2714 audio_extn_sound_trigger_stop_lab(in);
2715 in->standby = 1;
2716 }
2717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002719 if (adev->adm_deregister_stream)
2720 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2721
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002722 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002724 if (in->pcm) {
2725 pcm_close(in->pcm);
2726 in->pcm = NULL;
2727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002729 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 }
2731 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002732 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 return status;
2734}
2735
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002736static int in_dump(const struct audio_stream *stream __unused,
2737 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738{
2739 return 0;
2740}
2741
2742static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2743{
2744 struct stream_in *in = (struct stream_in *)stream;
2745 struct audio_device *adev = in->dev;
2746 struct str_parms *parms;
2747 char *str;
2748 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002749 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302751 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 parms = str_parms_create_str(kvpairs);
2753
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302754 if (!parms)
2755 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002756 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002757 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002758
2759 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2760 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 val = atoi(value);
2762 /* no audio source uses val == 0 */
2763 if ((in->source != val) && (val != 0)) {
2764 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002765 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2766 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2767 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2768 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002769 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002770 err = voice_extn_compress_voip_open_input_stream(in);
2771 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002772 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002773 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002774 }
2775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 }
2777 }
2778
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002779 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2780 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002782 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 in->device = val;
2784 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002785 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002786 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 }
2788 }
2789
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002790done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002792 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793
2794 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302795error:
Eric Laurent994a6932013-07-17 11:51:42 -07002796 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797 return ret;
2798}
2799
2800static char* in_get_parameters(const struct audio_stream *stream,
2801 const char *keys)
2802{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002803 struct stream_in *in = (struct stream_in *)stream;
2804 struct str_parms *query = str_parms_create_str(keys);
2805 char *str;
2806 char value[256];
2807 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002808
2809 if (!query || !reply) {
2810 ALOGE("in_get_parameters: failed to create query or reply");
2811 return NULL;
2812 }
2813
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002814 ALOGV("%s: enter: keys - %s", __func__, keys);
2815
2816 voice_extn_in_get_parameters(in, query, reply);
2817
2818 str = str_parms_to_str(reply);
2819 str_parms_destroy(query);
2820 str_parms_destroy(reply);
2821
2822 ALOGV("%s: exit: returns - %s", __func__, str);
2823 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824}
2825
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002826static int in_set_gain(struct audio_stream_in *stream __unused,
2827 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828{
2829 return 0;
2830}
2831
2832static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2833 size_t bytes)
2834{
2835 struct stream_in *in = (struct stream_in *)stream;
2836 struct audio_device *adev = in->dev;
2837 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302838 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002840 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302841
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002842 if (in->is_st_session) {
2843 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2844 /* Read from sound trigger HAL */
2845 audio_extn_sound_trigger_read(in, buffer, bytes);
2846 pthread_mutex_unlock(&in->lock);
2847 return bytes;
2848 }
2849
2850 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2851 ALOGD(" %s: sound card is not active/SSR state", __func__);
2852 ret= -EIO;;
2853 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302854 }
2855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002857 pthread_mutex_lock(&adev->lock);
2858 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2859 ret = voice_extn_compress_voip_start_input_stream(in);
2860 else
2861 ret = start_input_stream(in);
2862 pthread_mutex_unlock(&adev->lock);
2863 if (ret != 0) {
2864 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 }
2866 in->standby = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002867 if (adev->adm_register_input_stream)
2868 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002871 if (adev->adm_request_focus)
2872 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 if (in->pcm) {
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07002875 if (audio_extn_ssr_get_stream() == in)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002876 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002877 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2878 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002879 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2880 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002881 else
2882 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302883 if (ret < 0)
2884 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885 }
2886
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002887 if (adev->adm_abandon_focus)
2888 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 /*
2891 * Instead of writing zeroes here, we could trust the hardware
2892 * to always provide zeroes when muted.
2893 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302894 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2895 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 memset(buffer, 0, bytes);
2897
2898exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302899 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302900 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07002901 if (-ENETRESET == ret)
2902 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002904 pthread_mutex_unlock(&in->lock);
2905
2906 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302907 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302908 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302909 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302910 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302911 in->standby = true;
2912 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302913 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002915 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002916 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302917 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 }
2919 return bytes;
2920}
2921
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002922static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923{
2924 return 0;
2925}
2926
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002927static int add_remove_audio_effect(const struct audio_stream *stream,
2928 effect_handle_t effect,
2929 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002931 struct stream_in *in = (struct stream_in *)stream;
2932 int status = 0;
2933 effect_descriptor_t desc;
2934
2935 status = (*effect)->get_descriptor(effect, &desc);
2936 if (status != 0)
2937 return status;
2938
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002939 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002940 pthread_mutex_lock(&in->dev->lock);
2941 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2942 in->enable_aec != enable &&
2943 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2944 in->enable_aec = enable;
2945 if (!in->standby)
2946 select_devices(in->dev, in->usecase);
2947 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002948 if (in->enable_ns != enable &&
2949 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2950 in->enable_ns = enable;
2951 if (!in->standby)
2952 select_devices(in->dev, in->usecase);
2953 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002954 pthread_mutex_unlock(&in->dev->lock);
2955 pthread_mutex_unlock(&in->lock);
2956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 return 0;
2958}
2959
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002960static int in_add_audio_effect(const struct audio_stream *stream,
2961 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962{
Eric Laurent994a6932013-07-17 11:51:42 -07002963 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002964 return add_remove_audio_effect(stream, effect, true);
2965}
2966
2967static int in_remove_audio_effect(const struct audio_stream *stream,
2968 effect_handle_t effect)
2969{
Eric Laurent994a6932013-07-17 11:51:42 -07002970 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002971 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972}
2973
2974static int adev_open_output_stream(struct audio_hw_device *dev,
2975 audio_io_handle_t handle,
2976 audio_devices_t devices,
2977 audio_output_flags_t flags,
2978 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002979 struct audio_stream_out **stream_out,
2980 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981{
2982 struct audio_device *adev = (struct audio_device *)dev;
2983 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002984 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002985 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302988
2989 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2990 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07002991 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302992 return -EINVAL;
2993 }
2994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2996
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302997 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2998 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2999 devices, flags, &out->stream);
3000
3001
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003002 if (!out) {
3003 return -ENOMEM;
3004 }
3005
Haynes Mathew George204045b2015-02-25 20:32:03 -08003006 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003007 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003008 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 if (devices == AUDIO_DEVICE_NONE)
3011 devices = AUDIO_DEVICE_OUT_SPEAKER;
3012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 out->flags = flags;
3014 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003015 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003016 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017 out->sample_rate = config->sample_rate;
3018 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3019 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003020 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003021 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003022 out->non_blocking = 0;
3023 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024
3025 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003026 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
3027 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003028 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3029 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3030
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003031 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003032 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
3033 ret = read_hdmi_channel_masks(out);
3034
3035 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3036 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003037 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003038 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003039 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003040
3041 if (config->sample_rate == 0)
3042 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3043 if (config->channel_mask == 0)
3044 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3045
3046 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3049 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003051 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003053 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3054 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003055 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003056 ret = voice_extn_compress_voip_open_output_stream(out);
3057 if (ret != 0) {
3058 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3059 __func__, ret);
3060 goto error_open;
3061 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003062 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3063 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3064
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3066 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3067 ALOGE("%s: Unsupported Offload information", __func__);
3068 ret = -EINVAL;
3069 goto error_open;
3070 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003071
3072 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3073 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
3074 ALOGV("read and update_pass through formats");
3075 ret = audio_extn_dolby_update_passt_formats(adev, out);
3076 if(ret != 0) {
3077 goto error_open;
3078 }
3079 if(config->offload_info.format == 0)
3080 config->offload_info.format = out->supported_formats[0];
3081 }
3082
Mingming Yin90310102013-11-13 16:57:00 -08003083 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003084 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003085 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 ret = -EINVAL;
3087 goto error_open;
3088 }
3089
3090 out->compr_config.codec = (struct snd_codec *)
3091 calloc(1, sizeof(struct snd_codec));
3092
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003093 if (!out->compr_config.codec) {
3094 ret = -ENOMEM;
3095 goto error_open;
3096 }
3097
vivek mehta0ea887a2015-08-26 14:01:20 -07003098 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
vivek mehta446c3962015-09-14 10:57:35 -07003099 out->usecase = get_offload_usecase(adev, true);
3100 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003101 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003102 out->stream.set_callback = out_set_callback;
3103 out->stream.pause = out_pause;
3104 out->stream.resume = out_resume;
3105 out->stream.drain = out_drain;
3106 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003107 out->usecase = get_offload_usecase(adev, false);
3108 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003109 }
vivek mehta446c3962015-09-14 10:57:35 -07003110
3111 if (out->usecase == USECASE_INVALID) {
3112 ALOGE("%s: Max allowed OFFLOAD usecase reached ... ");
3113 ret = -EEXIST;
3114 goto error_open;
3115 }
3116
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 if (config->offload_info.channel_mask)
3118 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003119 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003121 config->offload_info.channel_mask = config->channel_mask;
3122 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003123 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 out->sample_rate = config->offload_info.sample_rate;
3125
Mingming Yin3ee55c62014-08-04 14:23:35 -07003126 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003128 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08003129 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003130 audio_extn_dolby_get_snd_codec_id(adev, out,
3131 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08003132 else
3133 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134 get_snd_codec_id(config->offload_info.format);
vivek mehta0ea887a2015-08-26 14:01:20 -07003135
3136 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
3137 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003138 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003139 platform_get_pcm_offload_buffer_size(&config->offload_info);
3140 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
3141 out->compr_config.fragment_size =
3142 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003143 } else {
3144 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003145 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003146 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003147 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3148 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003149 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 out->compr_config.codec->bit_rate =
3151 config->offload_info.bit_rate;
3152 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003153 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003154 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303155 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003156 /*TODO: Do we need to change it for passthrough */
3157 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158
Manish Dewangana6fc5442015-08-24 20:30:31 +05303159 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3160 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3161 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3162 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003163 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3164 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003165 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003166 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehta0ea887a2015-08-26 14:01:20 -07003167 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3168 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003169
Mingming Yin3ee55c62014-08-04 14:23:35 -07003170 if (out->bit_width == 24) {
3171 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3172 }
3173
Amit Shekhar6f461b12014-08-01 14:52:58 -07003174 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303175 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003176
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003177 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3178 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003179
Mingming Yin497419f2015-07-01 16:57:32 -07003180 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003181 //this flag is set from framework only if its for PCM formats
3182 //no need to check for PCM format again
3183 out->non_blocking = 0;
3184 out->use_small_bufs = true;
3185 ALOGI("Keep write blocking for small buff: non_blockling %d",
3186 out->non_blocking);
3187 }
3188
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003189 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303190 out->send_next_track_params = false;
3191 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003192 out->offload_state = OFFLOAD_STATE_IDLE;
3193 out->playback_started = 0;
3194
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003195 audio_extn_dts_create_state_notifier_node(out->usecase);
3196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 create_offload_callback_thread(out);
3198 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3199 __func__, config->offload_info.version,
3200 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003201 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003202 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003203 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3204 ret = voice_check_and_set_incall_music_usecase(adev, out);
3205 if (ret != 0) {
3206 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3207 __func__, ret);
3208 goto error_open;
3209 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003210 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3211 if (config->sample_rate == 0)
3212 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3213 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3214 config->sample_rate != 8000) {
3215 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3216 ret = -EINVAL;
3217 goto error_open;
3218 }
3219 out->sample_rate = config->sample_rate;
3220 out->config.rate = config->sample_rate;
3221 if (config->format == AUDIO_FORMAT_DEFAULT)
3222 config->format = AUDIO_FORMAT_PCM_16_BIT;
3223 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3224 config->format = AUDIO_FORMAT_PCM_16_BIT;
3225 ret = -EINVAL;
3226 goto error_open;
3227 }
3228 out->format = config->format;
3229 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3230 out->config = pcm_config_afe_proxy_playback;
3231 adev->voice_tx_output = out;
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003232 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3233 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3234 out->config = pcm_config_low_latency;
3235 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003236 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003237 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3239 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003240 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003241 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3242 format = AUDIO_FORMAT_PCM_16_BIT;
3243 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3244 out->config = pcm_config_deep_buffer;
3245 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003246 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003247 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003248 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003249 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003250 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003251 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 }
3253
Amit Shekhar1d896042014-10-03 13:16:09 -07003254 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3255 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003256 /* TODO remove this hardcoding and check why width is zero*/
3257 if (out->bit_width == 0)
3258 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003259 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3260 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003261 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303262 out->bit_width, out->channel_mask,
3263 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003264 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3265 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3266 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003267 if(adev->primary_output == NULL)
3268 adev->primary_output = out;
3269 else {
3270 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003271 ret = -EEXIST;
3272 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003273 }
3274 }
3275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 /* Check if this usecase is already existing */
3277 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003278 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3279 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003282 ret = -EEXIST;
3283 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284 }
3285 pthread_mutex_unlock(&adev->lock);
3286
3287 out->stream.common.get_sample_rate = out_get_sample_rate;
3288 out->stream.common.set_sample_rate = out_set_sample_rate;
3289 out->stream.common.get_buffer_size = out_get_buffer_size;
3290 out->stream.common.get_channels = out_get_channels;
3291 out->stream.common.get_format = out_get_format;
3292 out->stream.common.set_format = out_set_format;
3293 out->stream.common.standby = out_standby;
3294 out->stream.common.dump = out_dump;
3295 out->stream.common.set_parameters = out_set_parameters;
3296 out->stream.common.get_parameters = out_get_parameters;
3297 out->stream.common.add_audio_effect = out_add_audio_effect;
3298 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3299 out->stream.get_latency = out_get_latency;
3300 out->stream.set_volume = out_set_volume;
3301 out->stream.write = out_write;
3302 out->stream.get_render_position = out_get_render_position;
3303 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003304 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003307 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003308 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309
3310 config->format = out->stream.common.get_format(&out->stream.common);
3311 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3312 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3313
3314 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303315 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003316 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003317
3318 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3319 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3320 popcount(out->channel_mask), out->playback_started);
3321
Eric Laurent994a6932013-07-17 11:51:42 -07003322 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003324
3325error_open:
3326 free(out);
3327 *stream_out = NULL;
3328 ALOGD("%s: exit: ret %d", __func__, ret);
3329 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330}
3331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003332static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 struct audio_stream_out *stream)
3334{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 struct stream_out *out = (struct stream_out *)stream;
3336 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003337 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003338
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303339 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3340
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003341 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303342 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003343 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303344 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003345 if(ret != 0)
3346 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3347 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003348 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003349 out_standby(&stream->common);
3350
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003351 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003352 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003354 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003355 if (out->compr_config.codec != NULL)
3356 free(out->compr_config.codec);
3357 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003358
3359 if (adev->voice_tx_output == out)
3360 adev->voice_tx_output = NULL;
3361
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 pthread_cond_destroy(&out->cond);
3363 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003365 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366}
3367
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003368static void close_compress_sessions(struct audio_device *adev)
3369{
Mingming Yin7b762e72015-03-04 13:47:32 -08003370 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303371 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003372 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003373 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303374
3375 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003376 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303377 if (is_offload_usecase(usecase->id)) {
3378 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003379 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3380 out = usecase->stream.out;
3381 pthread_mutex_unlock(&adev->lock);
3382 out_standby(&out->stream.common);
3383 pthread_mutex_lock(&adev->lock);
3384 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303385 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003386 }
3387 pthread_mutex_unlock(&adev->lock);
3388}
3389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3391{
3392 struct audio_device *adev = (struct audio_device *)dev;
3393 struct str_parms *parms;
3394 char *str;
3395 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003396 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003397 int ret;
3398 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003400 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303403 if (!parms)
3404 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003405 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3406 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303407 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303408 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303409 struct listnode *node;
3410 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303411 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303412 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003413 //close compress sessions on OFFLINE status
3414 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303415 } else if (strstr(snd_card_status, "ONLINE")) {
3416 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303417 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003418 //send dts hpx license if enabled
3419 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303420 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303421 }
3422
3423 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003424 status = voice_set_parameters(adev, parms);
3425 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003426 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003428 status = platform_set_parameters(adev->platform, parms);
3429 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003430 goto done;
3431
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003432 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3433 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003434 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3436 adev->bluetooth_nrec = true;
3437 else
3438 adev->bluetooth_nrec = false;
3439 }
3440
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003441 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3442 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3444 adev->screen_off = false;
3445 else
3446 adev->screen_off = true;
3447 }
3448
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003449 ret = str_parms_get_int(parms, "rotation", &val);
3450 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003451 bool reverse_speakers = false;
3452 switch(val) {
3453 // FIXME: note that the code below assumes that the speakers are in the correct placement
3454 // relative to the user when the device is rotated 90deg from its default rotation. This
3455 // assumption is device-specific, not platform-specific like this code.
3456 case 270:
3457 reverse_speakers = true;
3458 break;
3459 case 0:
3460 case 90:
3461 case 180:
3462 break;
3463 default:
3464 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003465 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003466 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003467 if (status == 0) {
3468 if (adev->speaker_lr_swap != reverse_speakers) {
3469 adev->speaker_lr_swap = reverse_speakers;
3470 // only update the selected device if there is active pcm playback
3471 struct audio_usecase *usecase;
3472 struct listnode *node;
3473 list_for_each(node, &adev->usecase_list) {
3474 usecase = node_to_item(node, struct audio_usecase, list);
3475 if (usecase->type == PCM_PLAYBACK) {
3476 select_devices(adev, usecase->id);
3477 break;
3478 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003479 }
3480 }
3481 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003482 }
3483
Mingming Yin514a8bc2014-07-29 15:22:21 -07003484 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3485 if (ret >= 0) {
3486 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3487 adev->bt_wb_speech_enabled = true;
3488 else
3489 adev->bt_wb_speech_enabled = false;
3490 }
3491
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003492 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3493 if (ret >= 0) {
3494 val = atoi(value);
3495 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3496 ALOGV("cache new edid");
3497 platform_cache_edid(adev->platform);
3498 }
3499 }
3500
3501 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3502 if (ret >= 0) {
3503 val = atoi(value);
3504 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3505 ALOGV("invalidate cached edid");
3506 platform_invalidate_edid(adev->platform);
3507 }
3508 }
3509
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003510 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003511
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003512done:
3513 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003514 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303515error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003516 ALOGV("%s: exit with code(%d)", __func__, status);
3517 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518}
3519
3520static char* adev_get_parameters(const struct audio_hw_device *dev,
3521 const char *keys)
3522{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003523 struct audio_device *adev = (struct audio_device *)dev;
3524 struct str_parms *reply = str_parms_create();
3525 struct str_parms *query = str_parms_create_str(keys);
3526 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303527 char value[256] = {0};
3528 int ret = 0;
3529
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003530 if (!query || !reply) {
3531 ALOGE("adev_get_parameters: failed to create query or reply");
3532 return NULL;
3533 }
3534
Naresh Tannirud7205b62014-06-20 02:54:48 +05303535 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3536 sizeof(value));
3537 if (ret >=0) {
3538 int val = 1;
3539 pthread_mutex_lock(&adev->snd_card_status.lock);
3540 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3541 val = 0;
3542 pthread_mutex_unlock(&adev->snd_card_status.lock);
3543 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3544 goto exit;
3545 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003546
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003547 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003548 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003549 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003550 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303551 pthread_mutex_unlock(&adev->lock);
3552
Naresh Tannirud7205b62014-06-20 02:54:48 +05303553exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003554 str = str_parms_to_str(reply);
3555 str_parms_destroy(query);
3556 str_parms_destroy(reply);
3557
3558 ALOGV("%s: exit: returns - %s", __func__, str);
3559 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560}
3561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003562static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563{
3564 return 0;
3565}
3566
3567static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3568{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003569 int ret;
3570 struct audio_device *adev = (struct audio_device *)dev;
3571 pthread_mutex_lock(&adev->lock);
3572 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003573 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003574 pthread_mutex_unlock(&adev->lock);
3575 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576}
3577
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003578static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3579 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580{
3581 return -ENOSYS;
3582}
3583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003584static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3585 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586{
3587 return -ENOSYS;
3588}
3589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003590static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3591 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592{
3593 return -ENOSYS;
3594}
3595
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003596static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3597 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598{
3599 return -ENOSYS;
3600}
3601
3602static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3603{
3604 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 pthread_mutex_lock(&adev->lock);
3607 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003608 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003610 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3611 voice_is_in_call(adev)) {
3612 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07003613 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003614 adev->current_call_output = NULL;
3615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 }
3617 pthread_mutex_unlock(&adev->lock);
3618 return 0;
3619}
3620
3621static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3622{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003623 int ret;
3624
3625 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003626 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003627 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3628 pthread_mutex_unlock(&adev->lock);
3629
3630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631}
3632
3633static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3634{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003635 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 return 0;
3637}
3638
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003639static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 const struct audio_config *config)
3641{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003642 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003644 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3645 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646}
3647
3648static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003649 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 audio_devices_t devices,
3651 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003652 struct audio_stream_in **stream_in,
3653 audio_input_flags_t flags __unused,
3654 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003655 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656{
3657 struct audio_device *adev = (struct audio_device *)dev;
3658 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003659 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003660 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003661 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 *stream_in = NULL;
3664 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3665 return -EINVAL;
3666
3667 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003668
3669 if (!in) {
3670 ALOGE("failed to allocate input stream");
3671 return -ENOMEM;
3672 }
3673
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303674 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003675 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3676 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003678 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003679 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 in->stream.common.get_sample_rate = in_get_sample_rate;
3682 in->stream.common.set_sample_rate = in_set_sample_rate;
3683 in->stream.common.get_buffer_size = in_get_buffer_size;
3684 in->stream.common.get_channels = in_get_channels;
3685 in->stream.common.get_format = in_get_format;
3686 in->stream.common.set_format = in_set_format;
3687 in->stream.common.standby = in_standby;
3688 in->stream.common.dump = in_dump;
3689 in->stream.common.set_parameters = in_set_parameters;
3690 in->stream.common.get_parameters = in_get_parameters;
3691 in->stream.common.add_audio_effect = in_add_audio_effect;
3692 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3693 in->stream.set_gain = in_set_gain;
3694 in->stream.read = in_read;
3695 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3696
3697 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003698 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 in->standby = 1;
3701 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003702 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003703 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704
3705 /* Update config params with the requested sample rate and channels */
3706 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003707 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3708 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3709 is_low_latency = true;
3710#if LOW_LATENCY_CAPTURE_USE_CASE
3711 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3712#endif
3713 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003716 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003718 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303719 if (adev->mode != AUDIO_MODE_IN_CALL) {
3720 ret = -EINVAL;
3721 goto err_open;
3722 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003723 if (config->sample_rate == 0)
3724 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3725 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3726 config->sample_rate != 8000) {
3727 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3728 ret = -EINVAL;
3729 goto err_open;
3730 }
3731 if (config->format == AUDIO_FORMAT_DEFAULT)
3732 config->format = AUDIO_FORMAT_PCM_16_BIT;
3733 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3734 config->format = AUDIO_FORMAT_PCM_16_BIT;
3735 ret = -EINVAL;
3736 goto err_open;
3737 }
3738
3739 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3740 in->config = pcm_config_afe_proxy_record;
3741 in->config.channels = channel_count;
3742 in->config.rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05303743 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
3744 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07003745 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003746 audio_extn_compr_cap_format_supported(config->format) &&
3747 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003748 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003749 } else {
3750 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003751 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003752 buffer_size = get_input_buffer_size(config->sample_rate,
3753 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003754 channel_count,
3755 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003756 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003757 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3758 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3759 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3760 (in->config.rate == 8000 || in->config.rate == 16000) &&
3761 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3762 voice_extn_compress_voip_open_input_stream(in);
3763 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003766 /* This stream could be for sound trigger lab,
3767 get sound trigger pcm if present */
3768 audio_extn_sound_trigger_check_and_get_session(in);
3769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003771 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003772 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773
3774err_open:
3775 free(in);
3776 *stream_in = NULL;
3777 return ret;
3778}
3779
3780static void adev_close_input_stream(struct audio_hw_device *dev,
3781 struct audio_stream_in *stream)
3782{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003783 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003784 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003785 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303786
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303787 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003788
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303789 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07003790 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303791
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003792 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303793 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003794 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303795 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003796 if (ret != 0)
3797 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3798 __func__, ret);
3799 } else
3800 in_standby(&stream->common);
3801
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07003802 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003803 audio_extn_ssr_deinit();
3804 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Mingming Yine62d7842013-10-25 16:26:03 -07003806 if(audio_extn_compr_cap_enabled() &&
3807 audio_extn_compr_cap_format_supported(in->config.format))
3808 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003809
3810 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 return;
3812}
3813
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003814static int adev_dump(const audio_hw_device_t *device __unused,
3815 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816{
3817 return 0;
3818}
3819
3820static int adev_close(hw_device_t *device)
3821{
3822 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003823
3824 if (!adev)
3825 return 0;
3826
3827 pthread_mutex_lock(&adev_init_lock);
3828
3829 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003830 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003831 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003832 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003833 audio_route_free(adev->audio_route);
3834 free(adev->snd_dev_ref_cnt);
3835 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003836 if (adev->adm_deinit)
3837 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003838 free(device);
3839 adev = NULL;
3840 }
3841 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 return 0;
3844}
3845
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003846/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3847 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3848 * just that it _might_ work.
3849 */
3850static int period_size_is_plausible_for_low_latency(int period_size)
3851{
3852 switch (period_size) {
3853 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07003854 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003855 case 240:
3856 case 320:
3857 case 480:
3858 return 1;
3859 default:
3860 return 0;
3861 }
3862}
3863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864static int adev_open(const hw_module_t *module, const char *name,
3865 hw_device_t **device)
3866{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003867 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003869 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3871
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003872 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003873 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003874 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003875 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003876 ALOGD("%s: returning existing instance of adev", __func__);
3877 ALOGD("%s: exit", __func__);
3878 pthread_mutex_unlock(&adev_init_lock);
3879 return 0;
3880 }
3881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882 adev = calloc(1, sizeof(struct audio_device));
3883
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003884 if (!adev) {
3885 pthread_mutex_unlock(&adev_init_lock);
3886 return -ENOMEM;
3887 }
3888
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003889 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3892 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3893 adev->device.common.module = (struct hw_module_t *)module;
3894 adev->device.common.close = adev_close;
3895
3896 adev->device.init_check = adev_init_check;
3897 adev->device.set_voice_volume = adev_set_voice_volume;
3898 adev->device.set_master_volume = adev_set_master_volume;
3899 adev->device.get_master_volume = adev_get_master_volume;
3900 adev->device.set_master_mute = adev_set_master_mute;
3901 adev->device.get_master_mute = adev_get_master_mute;
3902 adev->device.set_mode = adev_set_mode;
3903 adev->device.set_mic_mute = adev_set_mic_mute;
3904 adev->device.get_mic_mute = adev_get_mic_mute;
3905 adev->device.set_parameters = adev_set_parameters;
3906 adev->device.get_parameters = adev_get_parameters;
3907 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3908 adev->device.open_output_stream = adev_open_output_stream;
3909 adev->device.close_output_stream = adev_close_output_stream;
3910 adev->device.open_input_stream = adev_open_input_stream;
3911 adev->device.close_input_stream = adev_close_input_stream;
3912 adev->device.dump = adev_dump;
3913
3914 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003916 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003917 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003920 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003921 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003922 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003923 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003924 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003925 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003926 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05303927 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303928 adev->perf_lock_opts[0] = 0x101;
3929 adev->perf_lock_opts[1] = 0x20E;
3930 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303931
3932 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3933 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003935 adev->platform = platform_init(adev);
3936 if (!adev->platform) {
3937 free(adev->snd_dev_ref_cnt);
3938 free(adev);
3939 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3940 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003941 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003942 return -EINVAL;
3943 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003944
Naresh Tanniru4c630392014-05-12 01:05:52 +05303945 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3946
Eric Laurentc4aef752013-09-12 17:45:53 -07003947 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3948 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3949 if (adev->visualizer_lib == NULL) {
3950 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3951 } else {
3952 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3953 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003954 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003955 "visualizer_hal_start_output");
3956 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003957 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003958 "visualizer_hal_stop_output");
3959 }
3960 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003961 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003962 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003963
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003964 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3965 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3966 if (adev->offload_effects_lib == NULL) {
3967 ALOGE("%s: DLOPEN failed for %s", __func__,
3968 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3969 } else {
3970 ALOGV("%s: DLOPEN successful for %s", __func__,
3971 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3972 adev->offload_effects_start_output =
3973 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3974 "offload_effects_bundle_hal_start_output");
3975 adev->offload_effects_stop_output =
3976 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3977 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003978 adev->offload_effects_set_hpx_state =
3979 (int (*)(bool))dlsym(adev->offload_effects_lib,
3980 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05303981 adev->offload_effects_get_parameters =
3982 (void (*)(struct str_parms *, struct str_parms *))
3983 dlsym(adev->offload_effects_lib,
3984 "offload_effects_bundle_get_parameters");
3985 adev->offload_effects_set_parameters =
3986 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3987 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003988 }
3989 }
3990
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003991 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3992 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3993 if (adev->adm_lib == NULL) {
3994 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3995 } else {
3996 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3997 adev->adm_init = (adm_init_t)
3998 dlsym(adev->adm_lib, "adm_init");
3999 adev->adm_deinit = (adm_deinit_t)
4000 dlsym(adev->adm_lib, "adm_deinit");
4001 adev->adm_register_input_stream = (adm_register_input_stream_t)
4002 dlsym(adev->adm_lib, "adm_register_input_stream");
4003 adev->adm_register_output_stream = (adm_register_output_stream_t)
4004 dlsym(adev->adm_lib, "adm_register_output_stream");
4005 adev->adm_deregister_stream = (adm_deregister_stream_t)
4006 dlsym(adev->adm_lib, "adm_deregister_stream");
4007 adev->adm_request_focus = (adm_request_focus_t)
4008 dlsym(adev->adm_lib, "adm_request_focus");
4009 adev->adm_abandon_focus = (adm_abandon_focus_t)
4010 dlsym(adev->adm_lib, "adm_abandon_focus");
4011 }
4012 }
4013
Mingming Yin514a8bc2014-07-29 15:22:21 -07004014 adev->bt_wb_speech_enabled = false;
4015
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004016 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017 *device = &adev->device.common;
4018
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004019 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4020 &adev->streams_output_cfg_list);
4021
Kiran Kandi910e1862013-10-29 13:29:42 -07004022 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004023
4024 char value[PROPERTY_VALUE_MAX];
4025 int trial;
4026 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4027 trial = atoi(value);
4028 if (period_size_is_plausible_for_low_latency(trial)) {
4029 pcm_config_low_latency.period_size = trial;
4030 pcm_config_low_latency.start_threshold = trial / 4;
4031 pcm_config_low_latency.avail_min = trial / 4;
4032 configured_low_latency_capture_period_size = trial;
4033 }
4034 }
4035 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4036 trial = atoi(value);
4037 if (period_size_is_plausible_for_low_latency(trial)) {
4038 configured_low_latency_capture_period_size = trial;
4039 }
4040 }
4041
vivek mehta446c3962015-09-14 10:57:35 -07004042 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004043 pthread_mutex_unlock(&adev_init_lock);
4044
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004045 if (adev->adm_init)
4046 adev->adm_data = adev->adm_init();
4047
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304048 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004049 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 return 0;
4051}
4052
4053static struct hw_module_methods_t hal_module_methods = {
4054 .open = adev_open,
4055};
4056
4057struct audio_module HAL_MODULE_INFO_SYM = {
4058 .common = {
4059 .tag = HARDWARE_MODULE_TAG,
4060 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4061 .hal_api_version = HARDWARE_HAL_API_VERSION,
4062 .id = AUDIO_HARDWARE_MODULE_ID,
4063 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004064 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065 .methods = &hal_module_methods,
4066 },
4067};