blob: 308a6a81c41316dfff5210ff8ec811cd8bafe34d [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",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -0700180 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Naresh Tanniru06f99432015-08-26 14:01:20 -0700181 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700184 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700186 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700187 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800188 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800189 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700190 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700191
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700192 [USECASE_VOICE2_CALL] = "voice2-call",
193 [USECASE_VOLTE_CALL] = "volte-call",
194 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800195 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800196 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
197 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800198 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700199 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
200 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800202 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
203 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
204 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
205
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700206 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
207 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700208 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
209 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700210
211 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
212 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700213};
214
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700215static const audio_usecase_t offload_usecases[] = {
216 USECASE_AUDIO_PLAYBACK_OFFLOAD,
217#ifdef MULTIPLE_OFFLOAD_ENABLED
218 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
223 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
224 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
225 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
226#endif
Naresh Tanniru06f99432015-08-26 14:01:20 -0700227 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700228};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800229
230#define STRING_TO_ENUM(string) { #string, string }
231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800232struct string_to_enum {
233 const char *name;
234 uint32_t value;
235};
236
237static const struct string_to_enum out_channels_name_to_enum_table[] = {
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
241 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
242 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
245};
246
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700247static const struct string_to_enum out_formats_name_to_enum_table[] = {
248 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
249 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
250 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
251};
252
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700253static struct audio_device *adev = NULL;
254static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700255static unsigned int audio_device_ref_count;
256
Haynes Mathew George5191a852013-09-11 14:19:36 -0700257static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800258
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800259static int check_and_set_gapless_mode(struct audio_device *adev) {
260
261
262 char value[PROPERTY_VALUE_MAX] = {0};
263 bool gapless_enabled = false;
264 const char *mixer_ctl_name = "Compress Gapless Playback";
265 struct mixer_ctl *ctl;
266
267 ALOGV("%s:", __func__);
268 property_get("audio.offload.gapless.enabled", value, NULL);
269 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
270
271 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
272 if (!ctl) {
273 ALOGE("%s: Could not get ctl for mixer cmd - %s",
274 __func__, mixer_ctl_name);
275 return -EINVAL;
276 }
277
278 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
279 ALOGE("%s: Could not set gapless mode %d",
280 __func__, gapless_enabled);
281 return -EINVAL;
282 }
283 return 0;
284}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700285
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700286static bool is_supported_format(audio_format_t format)
287{
Eric Laurent86e17132013-09-12 17:49:30 -0700288 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530289 format == AUDIO_FORMAT_AAC_LC ||
290 format == AUDIO_FORMAT_AAC_HE_V1 ||
291 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangan93672f12015-08-24 20:30:31 +0530292 format == AUDIO_FORMAT_AAC_ADTS_LC ||
293 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
294 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800295 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700296 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Naresh Tanniru06f99432015-08-26 14:01:20 -0700297 format == AUDIO_FORMAT_PCM_16_BIT ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800298 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530299 format == AUDIO_FORMAT_ALAC ||
300 format == AUDIO_FORMAT_APE ||
301 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800302 format == AUDIO_FORMAT_WMA ||
303 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800304 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700305
306 return false;
307}
308
309static int get_snd_codec_id(audio_format_t format)
310{
311 int id = 0;
312
Ashish Jainf9b78162014-08-25 20:36:25 +0530313 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700314 case AUDIO_FORMAT_MP3:
315 id = SND_AUDIOCODEC_MP3;
316 break;
317 case AUDIO_FORMAT_AAC:
318 id = SND_AUDIOCODEC_AAC;
319 break;
Manish Dewangan93672f12015-08-24 20:30:31 +0530320 case AUDIO_FORMAT_AAC_ADTS:
321 id = SND_AUDIOCODEC_AAC;
322 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530323 case AUDIO_FORMAT_PCM_OFFLOAD:
Naresh Tanniru06f99432015-08-26 14:01:20 -0700324 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800325 id = SND_AUDIOCODEC_PCM;
326 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700327 case AUDIO_FORMAT_FLAC:
328 id = SND_AUDIOCODEC_FLAC;
329 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530330 case AUDIO_FORMAT_ALAC:
331 id = SND_AUDIOCODEC_ALAC;
332 break;
333 case AUDIO_FORMAT_APE:
334 id = SND_AUDIOCODEC_APE;
335 break;
336 case AUDIO_FORMAT_VORBIS:
337 id = SND_AUDIOCODEC_VORBIS;
338 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800339 case AUDIO_FORMAT_WMA:
340 id = SND_AUDIOCODEC_WMA;
341 break;
342 case AUDIO_FORMAT_WMA_PRO:
343 id = SND_AUDIOCODEC_WMA_PRO;
344 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700345 default:
Mingming Yin90310102013-11-13 16:57:00 -0800346 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700347 }
348
349 return id;
350}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800351
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530352int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530353{
354 int snd_scard_state;
355
356 if (!adev)
357 return SND_CARD_STATE_OFFLINE;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 snd_scard_state = adev->snd_card_status.state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return snd_scard_state;
364}
365
366static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
367{
368 if (!adev)
369 return -ENOSYS;
370
371 pthread_mutex_lock(&adev->snd_card_status.lock);
372 adev->snd_card_status.state = snd_scard_state;
373 pthread_mutex_unlock(&adev->snd_card_status.lock);
374
375 return 0;
376}
377
Avinash Vaish71a8b972014-07-24 15:36:33 +0530378static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
379 struct audio_usecase *uc_info)
380{
381 struct listnode *node;
382 struct audio_usecase *usecase;
383
384 if (uc_info == NULL)
385 return -EINVAL;
386
387 /* Re-route all voice usecases on the shared backend other than the
388 specified usecase to new snd devices */
389 list_for_each(node, &adev->usecase_list) {
390 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800391 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530392 enable_audio_route(adev, usecase);
393 }
394 return 0;
395}
396
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700397int pcm_ioctl(struct pcm *pcm, int request, ...)
398{
399 va_list ap;
400 void * arg;
401 int pcm_fd = *(int*)pcm;
402
403 va_start(ap, request);
404 arg = va_arg(ap, void *);
405 va_end(ap);
406
407 return ioctl(pcm_fd, request, arg);
408}
409
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700410int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700411 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800412{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700413 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700414 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800415
416 if (usecase == NULL)
417 return -EINVAL;
418
419 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
420
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800421 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700422 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800423 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800425
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800426#ifdef DS1_DOLBY_DAP_ENABLED
427 audio_extn_dolby_set_dmid(adev);
428 audio_extn_dolby_set_endpoint(adev);
429#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700430 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700431 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530432 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700433 audio_extn_utils_send_app_type_cfg(usecase);
Dhananjay Kumarcb419212015-08-28 13:24:16 +0530434 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800435 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530436 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700437 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700438 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439 ALOGV("%s: exit", __func__);
440 return 0;
441}
442
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700443int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700444 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700446 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700447 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800448
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530449 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800450 return -EINVAL;
451
452 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700453 if (usecase->type == PCM_CAPTURE)
454 snd_device = usecase->in_snd_device;
455 else
456 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800457 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530458 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700459 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700460 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700461 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530462 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800463 ALOGV("%s: exit", __func__);
464 return 0;
465}
466
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700467int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700468 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800469{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700470 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
471
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800472 if (snd_device < SND_DEVICE_MIN ||
473 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800474 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800475 return -EINVAL;
476 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700477
478 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700479
480 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
481 ALOGE("%s: Invalid sound device returned", __func__);
482 return -EINVAL;
483 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700484 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700485 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700486 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700487 return 0;
488 }
489
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700490 if (audio_extn_spkr_prot_is_enabled())
491 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700492 /* start usb playback thread */
493 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
494 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
495 audio_extn_usb_start_playback(adev);
496
497 /* start usb capture thread */
498 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
499 audio_extn_usb_start_capture(adev);
500
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530501 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530502 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800503 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700505 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
506 adev->snd_dev_ref_cnt[snd_device]--;
507 return -EINVAL;
508 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200509 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800510 if (audio_extn_spkr_prot_start_processing(snd_device)) {
511 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200512 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800513 return -EINVAL;
514 }
515 } else {
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700516 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700517 /* due to the possibility of calibration overwrite between listen
518 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700519 audio_extn_sound_trigger_update_device_status(snd_device,
520 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530521 audio_extn_listen_update_device_status(snd_device,
522 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700523 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700524 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700525 audio_extn_sound_trigger_update_device_status(snd_device,
526 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530527 audio_extn_listen_update_device_status(snd_device,
528 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700529 return -EINVAL;
530 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300531 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700532 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800534 return 0;
535}
536
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700537int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700538 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
541
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800542 if (snd_device < SND_DEVICE_MIN ||
543 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800544 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800545 return -EINVAL;
546 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
548 ALOGE("%s: device ref cnt is already 0", __func__);
549 return -EINVAL;
550 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700552 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700553
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700554 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
555 ALOGE("%s: Invalid sound device returned", __func__);
556 return -EINVAL;
557 }
558
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700559 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -0700560 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800561 /* exit usb play back thread */
562 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
563 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
564 audio_extn_usb_stop_playback();
565
566 /* exit usb capture thread */
567 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700568 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800569
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530570 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530571 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800572 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700573 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700574 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300575 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700576 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300577 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700578
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530579 if (snd_device == SND_DEVICE_OUT_HDMI)
580 adev->mChannelStatusSet = false;
581
Linux Build Service Account75e43952015-08-26 19:58:56 -0700582 if (snd_device == SND_DEVICE_OUT_HDMI)
583 adev->mChannelStatusSet = false;
584
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200585 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700586 audio_extn_sound_trigger_update_device_status(snd_device,
587 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530588 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800589 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592 return 0;
593}
594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595static void check_usecases_codec_backend(struct audio_device *adev,
596 struct audio_usecase *uc_info,
597 snd_device_t snd_device)
598{
599 struct listnode *node;
600 struct audio_usecase *usecase;
601 bool switch_device[AUDIO_USECASE_MAX];
602 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530603 int backend_idx = DEFAULT_CODEC_BACKEND;
604 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605
606 /*
607 * This function is to make sure that all the usecases that are active on
608 * the hardware codec backend are always routed to any one device that is
609 * handled by the hardware codec.
610 * For example, if low-latency and deep-buffer usecases are currently active
611 * on speaker and out_set_parameters(headset) is received on low-latency
612 * output, then we have to make sure deep-buffer is also switched to headset,
613 * because of the limitation that both the devices cannot be enabled
614 * at the same time as they share the same backend.
615 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700616 /*
617 * This call is to check if we need to force routing for a particular stream
618 * If there is a backend configuration change for the device when a
619 * new stream starts, then ADM needs to be closed and re-opened with the new
620 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530621 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700622 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530623 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
624 snd_device);
625 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800627 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800628 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700629 for (i = 0; i < AUDIO_USECASE_MAX; i++)
630 switch_device[i] = false;
631
632 list_for_each(node, &adev->usecase_list) {
633 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530634
635 if (usecase == uc_info)
636 continue;
637 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
638 ALOGV("%s: backend_idx: %d,"
639 "usecase_backend_idx: %d, curr device: %s, usecase device:"
640 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530641 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530642
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800643 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700644 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530645 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
646 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530647 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530648 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700649 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700650 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 switch_device[usecase->id] = true;
652 num_uc_to_switch++;
653 }
654 }
655
656 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700657 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700658
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530659 /* Make sure the previous devices to be disabled first and then enable the
660 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661 list_for_each(node, &adev->usecase_list) {
662 usecase = node_to_item(node, struct audio_usecase, list);
663 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700664 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 }
666 }
667
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700668 list_for_each(node, &adev->usecase_list) {
669 usecase = node_to_item(node, struct audio_usecase, list);
670 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700671 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700672 }
673 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700674
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 /* Re-route all the usecases on the shared backend other than the
676 specified usecase to new snd devices */
677 list_for_each(node, &adev->usecase_list) {
678 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta5d596582015-08-20 12:30:33 +0530679 /* Update the out_snd_device only before enabling the audio route */
680 if (switch_device[usecase->id] ) {
681 usecase->out_snd_device = snd_device;
682 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530683 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 }
685 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686 }
687}
688
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700689static void check_and_route_capture_usecases(struct audio_device *adev,
690 struct audio_usecase *uc_info,
691 snd_device_t snd_device)
692{
693 struct listnode *node;
694 struct audio_usecase *usecase;
695 bool switch_device[AUDIO_USECASE_MAX];
696 int i, num_uc_to_switch = 0;
697
698 /*
699 * This function is to make sure that all the active capture usecases
700 * are always routed to the same input sound device.
701 * For example, if audio-record and voice-call usecases are currently
702 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
703 * is received for voice call then we have to make sure that audio-record
704 * usecase is also switched to earpiece i.e. voice-dmic-ef,
705 * because of the limitation that two devices cannot be enabled
706 * at the same time if they share the same backend.
707 */
708 for (i = 0; i < AUDIO_USECASE_MAX; i++)
709 switch_device[i] = false;
710
711 list_for_each(node, &adev->usecase_list) {
712 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800713 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700715 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700716 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Venkata Narendra Kumar Guttad4adfa82015-08-20 13:36:07 +0530717 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
718 (usecase->type == VOICE_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700719 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700720 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
721 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700722 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700723 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 switch_device[usecase->id] = true;
725 num_uc_to_switch++;
726 }
727 }
728
729 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700730 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530732 /* Make sure the previous devices to be disabled first and then enable the
733 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700734 list_for_each(node, &adev->usecase_list) {
735 usecase = node_to_item(node, struct audio_usecase, list);
736 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700737 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800738 }
739 }
740
741 list_for_each(node, &adev->usecase_list) {
742 usecase = node_to_item(node, struct audio_usecase, list);
743 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700744 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700745 }
746 }
747
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700748 /* Re-route all the usecases on the shared backend other than the
749 specified usecase to new snd devices */
750 list_for_each(node, &adev->usecase_list) {
751 usecase = node_to_item(node, struct audio_usecase, list);
752 /* Update the in_snd_device only before enabling the audio route */
753 if (switch_device[usecase->id] ) {
754 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800755 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530756 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700757 }
758 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700759 }
760}
761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800762/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700763static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800764{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700765 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700766 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767
768 switch (channels) {
769 /*
770 * Do not handle stereo output in Multi-channel cases
771 * Stereo case is handled in normal playback path
772 */
773 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700774 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
775 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
776 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
777 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
778 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
779 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780 break;
781 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700782 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
783 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789 break;
790 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700791 ALOGE("HDMI does not support multi channel playback");
792 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793 break;
794 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700795 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796}
797
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800798audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
799 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700800{
801 struct audio_usecase *usecase;
802 struct listnode *node;
803
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800806 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700807 ALOGV("%s: usecase id %d", __func__, usecase->id);
808 return usecase->id;
809 }
810 }
811 return USECASE_INVALID;
812}
813
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700814struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700815 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700816{
817 struct audio_usecase *usecase;
818 struct listnode *node;
819
820 list_for_each(node, &adev->usecase_list) {
821 usecase = node_to_item(node, struct audio_usecase, list);
822 if (usecase->id == uc_id)
823 return usecase;
824 }
825 return NULL;
826}
827
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700828int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800830 snd_device_t out_snd_device = SND_DEVICE_NONE;
831 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 struct audio_usecase *usecase = NULL;
833 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800834 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800835 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800836 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800837 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700838 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 usecase = get_usecase_from_list(adev, uc_id);
841 if (usecase == NULL) {
842 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
843 return -EINVAL;
844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800845
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800846 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800847 (usecase->type == VOIP_CALL) ||
848 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700849 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800850 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700851 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 usecase->devices = usecase->stream.out->devices;
853 } else {
854 /*
855 * If the voice call is active, use the sound devices of voice call usecase
856 * so that it would not result any device switch. All the usecases will
857 * be switched to new device when select_devices() is called for voice call
858 * usecase. This is to avoid switching devices for voice call when
859 * check_usecases_codec_backend() is called below.
860 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700861 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700862 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800863 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700864 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
865 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700866 in_snd_device = vc_usecase->in_snd_device;
867 out_snd_device = vc_usecase->out_snd_device;
868 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800869 } else if (voice_extn_compress_voip_is_active(adev)) {
870 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700871 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530872 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700873 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800874 in_snd_device = voip_usecase->in_snd_device;
875 out_snd_device = voip_usecase->out_snd_device;
876 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800877 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800878 hfp_ucid = audio_extn_hfp_get_usecase();
879 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700880 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800881 in_snd_device = hfp_usecase->in_snd_device;
882 out_snd_device = hfp_usecase->out_snd_device;
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 }
885 if (usecase->type == PCM_PLAYBACK) {
886 usecase->devices = usecase->stream.out->devices;
887 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700888 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700889 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800890 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 if (usecase->stream.out == adev->primary_output &&
892 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800893 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700894 select_devices(adev, adev->active_input->usecase);
895 }
896 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 } else if (usecase->type == PCM_CAPTURE) {
898 usecase->devices = usecase->stream.in->device;
899 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700900 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700901 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530902 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
903 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
904 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
905 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700906 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -0700907 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700908 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
909 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700910 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700911 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700912 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700913 }
914 }
915
916 if (out_snd_device == usecase->out_snd_device &&
917 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800918 return 0;
919 }
920
sangwoobc677242013-08-08 16:53:43 +0900921 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700922 out_snd_device, platform_get_snd_device_name(out_snd_device),
923 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800925 /*
926 * Limitation: While in call, to do a device switch we need to disable
927 * and enable both RX and TX devices though one of them is same as current
928 * device.
929 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700930 if ((usecase->type == VOICE_CALL) &&
931 (usecase->in_snd_device != SND_DEVICE_NONE) &&
932 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700933 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700934 }
935
936 if (((usecase->type == VOICE_CALL) ||
937 (usecase->type == VOIP_CALL)) &&
938 (usecase->out_snd_device != SND_DEVICE_NONE)) {
939 /* Disable sidetone only if voice/voip call already exists */
940 if (voice_is_call_state_active(adev) ||
941 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700942 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800943 }
944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 /* Disable current sound devices */
946 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700947 disable_audio_route(adev, usecase);
948 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800949 }
950
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700951 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700952 disable_audio_route(adev, usecase);
953 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954 }
955
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800956 /* Applicable only on the targets that has external modem.
957 * New device information should be sent to modem before enabling
958 * the devices to reduce in-call device switch time.
959 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700960 if ((usecase->type == VOICE_CALL) &&
961 (usecase->in_snd_device != SND_DEVICE_NONE) &&
962 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800963 status = platform_switch_voice_call_enable_device_config(adev->platform,
964 out_snd_device,
965 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700966 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 /* Enable new sound devices */
969 if (out_snd_device != SND_DEVICE_NONE) {
970 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
971 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700972 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 }
974
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 if (in_snd_device != SND_DEVICE_NONE) {
976 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700977 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979
Avinash Vaish71a8b972014-07-24 15:36:33 +0530980 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700981 status = platform_switch_voice_call_device_post(adev->platform,
982 out_snd_device,
983 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530984 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700985 /* Enable sidetone only if voice/voip call already exists */
986 if (voice_is_call_state_active(adev) ||
987 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700988 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530989 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800990
sangwoo170731f2013-06-08 15:36:36 +0900991 usecase->in_snd_device = in_snd_device;
992 usecase->out_snd_device = out_snd_device;
993
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530994 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700995 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530996 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700997 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530998 usecase->stream.out->flags,
999 usecase->stream.out->format,
1000 usecase->stream.out->sample_rate,
1001 usecase->stream.out->bit_width,
1002 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001003 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301004 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001005
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001006 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001007
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001008 /* Applicable only on the targets that has external modem.
1009 * Enable device command should be sent to modem only after
1010 * enabling voice call mixer controls
1011 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001012 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001013 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1014 out_snd_device,
1015 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301016 ALOGD("%s: done",__func__);
1017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 return status;
1019}
1020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021static int stop_input_stream(struct stream_in *in)
1022{
1023 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 struct audio_usecase *uc_info;
1025 struct audio_device *adev = in->dev;
1026
Eric Laurentc8400632013-02-14 19:04:54 -08001027 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Eric Laurent994a6932013-07-17 11:51:42 -07001029 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 uc_info = get_usecase_from_list(adev, in->usecase);
1032 if (uc_info == NULL) {
1033 ALOGE("%s: Could not find the usecase (%d) in the list",
1034 __func__, in->usecase);
1035 return -EINVAL;
1036 }
1037
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001038 /* Close in-call recording streams */
1039 voice_check_and_stop_incall_rec_usecase(adev, in);
1040
Eric Laurent150dbfe2013-02-27 14:31:02 -08001041 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001042 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043
1044 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001045 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001047 list_remove(&uc_info->list);
1048 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049
Eric Laurent994a6932013-07-17 11:51:42 -07001050 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051 return ret;
1052}
1053
1054int start_input_stream(struct stream_in *in)
1055{
1056 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001057 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 struct audio_usecase *uc_info;
1059 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301060 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301062 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1063 if (get_usecase_from_list(adev, usecase) == NULL)
1064 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301065 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1066 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001067
Naresh Tanniru80659832014-06-04 18:17:56 +05301068
1069 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301070 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301071 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301072 goto error_config;
1073 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301074
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001075 /* Check if source matches incall recording usecase criteria */
1076 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1077 if (ret)
1078 goto error_config;
1079 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301080 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1081
1082 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1083 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1084 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1085 goto error_config;
1086 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001087
Eric Laurentb23d5282013-05-14 15:27:20 -07001088 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 if (in->pcm_device_id < 0) {
1090 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1091 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001092 ret = -EINVAL;
1093 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095
1096 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001098
1099 if (!uc_info) {
1100 ret = -ENOMEM;
1101 goto error_config;
1102 }
1103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 uc_info->id = in->usecase;
1105 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001106 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 uc_info->devices = in->device;
1108 uc_info->in_snd_device = SND_DEVICE_NONE;
1109 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001111 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301112 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114
Eric Laurentc8400632013-02-14 19:04:54 -08001115 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001116 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1117
1118 unsigned int flags = PCM_IN;
1119 unsigned int pcm_open_retry_count = 0;
1120
1121 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1122 flags |= PCM_MMAP | PCM_NOIRQ;
1123 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1124 }
1125
1126 while (1) {
1127 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1128 flags, &in->config);
1129 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1130 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1131 if (in->pcm != NULL) {
1132 pcm_close(in->pcm);
1133 in->pcm = NULL;
1134 }
1135 if (pcm_open_retry_count-- == 0) {
1136 ret = -EIO;
1137 goto error_open;
1138 }
1139 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1140 continue;
1141 }
1142 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001143 }
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001144
1145 ALOGV("%s: pcm_prepare", __func__);
1146 ret = pcm_prepare(in->pcm);
1147 if (ret < 0) {
1148 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1149 pcm_close(in->pcm);
1150 in->pcm = NULL;
1151 goto error_open;
1152 }
1153
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301154 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301155
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001156 ALOGD("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001157
Eric Laurentc8400632013-02-14 19:04:54 -08001158 return ret;
1159
1160error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301162 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001163
1164error_config:
1165 adev->active_input = NULL;
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301166 /*
1167 * sleep 50ms to allow sufficient time for kernel
1168 * drivers to recover incases like SSR.
1169 */
1170 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001172
1173 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174}
1175
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001176void lock_input_stream(struct stream_in *in)
1177{
1178 pthread_mutex_lock(&in->pre_lock);
1179 pthread_mutex_lock(&in->lock);
1180 pthread_mutex_unlock(&in->pre_lock);
1181}
1182
1183void lock_output_stream(struct stream_out *out)
1184{
1185 pthread_mutex_lock(&out->pre_lock);
1186 pthread_mutex_lock(&out->lock);
1187 pthread_mutex_unlock(&out->pre_lock);
1188}
1189
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001190/* must be called with out->lock locked */
1191static int send_offload_cmd_l(struct stream_out* out, int command)
1192{
1193 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1194
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001195 if (!cmd) {
1196 ALOGE("failed to allocate mem for command 0x%x", command);
1197 return -ENOMEM;
1198 }
1199
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001200 ALOGVV("%s %d", __func__, command);
1201
1202 cmd->cmd = command;
1203 list_add_tail(&out->offload_cmd_list, &cmd->node);
1204 pthread_cond_signal(&out->offload_cond);
1205 return 0;
1206}
1207
1208/* must be called iwth out->lock locked */
1209static void stop_compressed_output_l(struct stream_out *out)
1210{
1211 out->offload_state = OFFLOAD_STATE_IDLE;
1212 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001213 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001214 if (out->compr != NULL) {
1215 compress_stop(out->compr);
1216 while (out->offload_thread_blocked) {
1217 pthread_cond_wait(&out->cond, &out->lock);
1218 }
1219 }
1220}
1221
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001222bool is_offload_usecase(audio_usecase_t uc_id)
1223{
1224 unsigned int i;
1225 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1226 if (uc_id == offload_usecases[i])
1227 return true;
1228 }
1229 return false;
1230}
1231
1232static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1233{
1234 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1235 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1236 char value[PROPERTY_VALUE_MAX] = {0};
1237
1238 property_get("audio.offload.multiple.enabled", value, NULL);
1239 if (!(atoi(value) || !strncmp("true", value, 4)))
1240 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1241
1242 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1243 for (i = 0; i < num_usecase; i++) {
1244 if (!(adev->offload_usecases_state & (0x1<<i))) {
1245 adev->offload_usecases_state |= 0x1 << i;
1246 ret = offload_usecases[i];
1247 break;
1248 }
1249 }
1250 ALOGV("%s: offload usecase is %d", __func__, ret);
1251 return ret;
1252}
1253
1254static void free_offload_usecase(struct audio_device *adev,
1255 audio_usecase_t uc_id)
1256{
1257 unsigned int i;
1258 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1259 if (offload_usecases[i] == uc_id) {
1260 adev->offload_usecases_state &= ~(0x1<<i);
1261 break;
1262 }
1263 }
1264 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1265}
1266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001267static void *offload_thread_loop(void *context)
1268{
1269 struct stream_out *out = (struct stream_out *) context;
1270 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001271 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001272
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001273 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1274 set_sched_policy(0, SP_FOREGROUND);
1275 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1276
1277 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001278 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001279 for (;;) {
1280 struct offload_cmd *cmd = NULL;
1281 stream_callback_event_t event;
1282 bool send_callback = false;
1283
1284 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1285 __func__, list_empty(&out->offload_cmd_list),
1286 out->offload_state);
1287 if (list_empty(&out->offload_cmd_list)) {
1288 ALOGV("%s SLEEPING", __func__);
1289 pthread_cond_wait(&out->offload_cond, &out->lock);
1290 ALOGV("%s RUNNING", __func__);
1291 continue;
1292 }
1293
1294 item = list_head(&out->offload_cmd_list);
1295 cmd = node_to_item(item, struct offload_cmd, node);
1296 list_remove(item);
1297
1298 ALOGVV("%s STATE %d CMD %d out->compr %p",
1299 __func__, out->offload_state, cmd->cmd, out->compr);
1300
1301 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1302 free(cmd);
1303 break;
1304 }
1305
1306 if (out->compr == NULL) {
1307 ALOGE("%s: Compress handle is NULL", __func__);
1308 pthread_cond_signal(&out->cond);
1309 continue;
1310 }
1311 out->offload_thread_blocked = true;
1312 pthread_mutex_unlock(&out->lock);
1313 send_callback = false;
1314 switch(cmd->cmd) {
1315 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001316 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001318 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 send_callback = true;
1320 event = STREAM_CBK_EVENT_WRITE_READY;
1321 break;
1322 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001323 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301324 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001325 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301326 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001327 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301328 if (ret < 0)
1329 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301330 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301331 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001332 compress_drain(out->compr);
1333 else
1334 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301335 if (ret != -ENETRESET) {
1336 send_callback = true;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301337 pthread_mutex_lock(&out->lock);
1338 out->send_new_metadata = 1;
1339 out->send_next_track_params = true;
1340 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301341 event = STREAM_CBK_EVENT_DRAIN_READY;
1342 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1343 } else
1344 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001345 break;
1346 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001347 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001348 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001349 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001350 send_callback = true;
1351 event = STREAM_CBK_EVENT_DRAIN_READY;
1352 break;
1353 default:
1354 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1355 break;
1356 }
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001357 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001358 out->offload_thread_blocked = false;
1359 pthread_cond_signal(&out->cond);
vivek mehtacc70d4b2015-09-25 14:07:43 -07001360 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001361 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001362 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001363 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001364 free(cmd);
1365 }
1366
1367 pthread_cond_signal(&out->cond);
1368 while (!list_empty(&out->offload_cmd_list)) {
1369 item = list_head(&out->offload_cmd_list);
1370 list_remove(item);
1371 free(node_to_item(item, struct offload_cmd, node));
1372 }
1373 pthread_mutex_unlock(&out->lock);
1374
1375 return NULL;
1376}
1377
1378static int create_offload_callback_thread(struct stream_out *out)
1379{
1380 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1381 list_init(&out->offload_cmd_list);
1382 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1383 offload_thread_loop, out);
1384 return 0;
1385}
1386
1387static int destroy_offload_callback_thread(struct stream_out *out)
1388{
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001389 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001390 stop_compressed_output_l(out);
1391 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1392
1393 pthread_mutex_unlock(&out->lock);
1394 pthread_join(out->offload_thread, (void **) NULL);
1395 pthread_cond_destroy(&out->offload_cond);
1396
1397 return 0;
1398}
1399
Eric Laurent07eeafd2013-10-06 12:52:49 -07001400static bool allow_hdmi_channel_config(struct audio_device *adev)
1401{
1402 struct listnode *node;
1403 struct audio_usecase *usecase;
1404 bool ret = true;
1405
1406 list_for_each(node, &adev->usecase_list) {
1407 usecase = node_to_item(node, struct audio_usecase, list);
1408 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1409 /*
1410 * If voice call is already existing, do not proceed further to avoid
1411 * disabling/enabling both RX and TX devices, CSD calls, etc.
1412 * Once the voice call done, the HDMI channels can be configured to
1413 * max channels of remaining use cases.
1414 */
1415 if (usecase->id == USECASE_VOICE_CALL) {
1416 ALOGD("%s: voice call is active, no change in HDMI channels",
1417 __func__);
1418 ret = false;
1419 break;
1420 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1421 ALOGD("%s: multi channel playback is active, "
1422 "no change in HDMI channels", __func__);
1423 ret = false;
1424 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001425 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001426 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001427 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1428 ", no change in HDMI channels", __func__,
1429 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001430 ret = false;
1431 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001432 }
1433 }
1434 }
1435 return ret;
1436}
1437
1438static int check_and_set_hdmi_channels(struct audio_device *adev,
1439 unsigned int channels)
1440{
1441 struct listnode *node;
1442 struct audio_usecase *usecase;
1443
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001444 unsigned int supported_channels = platform_edid_get_max_channels(
1445 adev->platform);
1446 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001447 /* Check if change in HDMI channel config is allowed */
1448 if (!allow_hdmi_channel_config(adev))
1449 return 0;
1450
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001451 if (channels > supported_channels)
1452 channels = supported_channels;
1453
Eric Laurent07eeafd2013-10-06 12:52:49 -07001454 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001455 ALOGD("%s: Requested channels are same as current channels(%d)",
1456 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001457 return 0;
1458 }
1459
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001460 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001461 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001462 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001463 adev->cur_hdmi_channels = channels;
1464
1465 /*
1466 * Deroute all the playback streams routed to HDMI so that
1467 * the back end is deactivated. Note that backend will not
1468 * be deactivated if any one stream is connected to it.
1469 */
1470 list_for_each(node, &adev->usecase_list) {
1471 usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_PLAYBACK &&
1473 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001474 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001475 }
1476 }
1477
1478 /*
1479 * Enable all the streams disabled above. Now the HDMI backend
1480 * will be activated with new channel configuration
1481 */
1482 list_for_each(node, &adev->usecase_list) {
1483 usecase = node_to_item(node, struct audio_usecase, list);
1484 if (usecase->type == PCM_PLAYBACK &&
1485 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001486 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001487 }
1488 }
1489
1490 return 0;
1491}
1492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493static int stop_output_stream(struct stream_out *out)
1494{
1495 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 struct audio_usecase *uc_info;
1497 struct audio_device *adev = out->dev;
1498
Eric Laurent994a6932013-07-17 11:51:42 -07001499 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 uc_info = get_usecase_from_list(adev, out->usecase);
1502 if (uc_info == NULL) {
1503 ALOGE("%s: Could not find the usecase (%d) in the list",
1504 __func__, out->usecase);
1505 return -EINVAL;
1506 }
1507
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001508 if (is_offload_usecase(out->usecase) &&
1509 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001510 if (adev->visualizer_stop_output != NULL)
1511 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001512
1513 audio_extn_dts_remove_state_notifier_node(out->usecase);
1514
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001515 if (adev->offload_effects_stop_output != NULL)
1516 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1517 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001518
Eric Laurent150dbfe2013-02-27 14:31:02 -08001519 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001520 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521
1522 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001523 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001525 list_remove(&uc_info->list);
1526 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001528 if (is_offload_usecase(out->usecase) &&
1529 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1530 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1531 ALOGV("Disable passthrough , reset mixer to pcm");
1532 /* NO_PASSTHROUGH */
1533 out->compr_config.codec->compr_passthr = 0;
1534 audio_extn_dolby_set_hdmi_config(adev, out);
1535 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1536 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001537 /* Must be called after removing the usecase from list */
1538 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1539 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1540
Eric Laurent994a6932013-07-17 11:51:42 -07001541 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001542 return ret;
1543}
1544
1545int start_output_stream(struct stream_out *out)
1546{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001548 int sink_channels = 0;
1549 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 struct audio_usecase *uc_info;
1551 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301552 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001554 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1555 ret = -EINVAL;
1556 goto error_config;
1557 }
1558
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301559 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1560 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1561 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301562
Naresh Tanniru80659832014-06-04 18:17:56 +05301563 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301564 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301565 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301566 goto error_config;
1567 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301568
Eric Laurentb23d5282013-05-14 15:27:20 -07001569 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 if (out->pcm_device_id < 0) {
1571 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1572 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001573 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001574 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 }
1576
1577 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001578
1579 if (!uc_info) {
1580 ret = -ENOMEM;
1581 goto error_config;
1582 }
1583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 uc_info->id = out->usecase;
1585 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001586 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 uc_info->devices = out->devices;
1588 uc_info->in_snd_device = SND_DEVICE_NONE;
1589 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001590 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001591 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001592 if (is_offload_usecase(out->usecase)) {
1593 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001594 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1595 }
1596 }
Mingming Yin9c041392014-05-01 15:37:31 -07001597 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1598 if (!strncmp("true", prop_value, 4)) {
1599 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001600 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1601 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001602 check_and_set_hdmi_channels(adev, sink_channels);
1603 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001604 if (is_offload_usecase(out->usecase)) {
1605 unsigned int ch_count = out->compr_config.codec->ch_in;
1606 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1607 /* backend channel config for passthrough stream is stereo */
1608 ch_count = 2;
1609 check_and_set_hdmi_channels(adev, ch_count);
1610 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001611 check_and_set_hdmi_channels(adev, out->config.channels);
1612 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001613 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001614 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001615 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001617 select_devices(adev, out->usecase);
1618
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001619 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1620 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001621 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001622 unsigned int flags = PCM_OUT;
1623 unsigned int pcm_open_retry_count = 0;
1624 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1625 flags |= PCM_MMAP | PCM_NOIRQ;
1626 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1627 } else
1628 flags |= PCM_MONOTONIC;
1629
1630 while (1) {
1631 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1632 flags, &out->config);
1633 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1634 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1635 if (out->pcm != NULL) {
1636 pcm_close(out->pcm);
1637 out->pcm = NULL;
1638 }
1639 if (pcm_open_retry_count-- == 0) {
1640 ret = -EIO;
1641 goto error_open;
1642 }
1643 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1644 continue;
1645 }
1646 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001648
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001649 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1650 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001651
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001652 ALOGV("%s: pcm_prepare", __func__);
1653 if (pcm_is_ready(out->pcm)) {
1654 ret = pcm_prepare(out->pcm);
1655 if (ret < 0) {
1656 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1657 pcm_close(out->pcm);
1658 out->pcm = NULL;
1659 goto error_open;
1660 }
1661 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001662 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001663 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1664 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001666 out->compr = compress_open(adev->snd_card,
1667 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001668 COMPRESS_IN, &out->compr_config);
1669 if (out->compr && !is_compress_ready(out->compr)) {
1670 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1671 compress_close(out->compr);
1672 out->compr = NULL;
1673 ret = -EIO;
1674 goto error_open;
1675 }
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301676 /* compress_open sends params of the track, so reset the flag here */
1677 out->is_compr_metadata_avail = false;
1678
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 if (out->offload_callback)
1680 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001681
Fred Oh3f43e742015-03-04 18:42:34 -08001682 /* Since small bufs uses blocking writes, a write will be blocked
1683 for the default max poll time (20s) in the event of an SSR.
1684 Reduce the poll time to observe and deal with SSR faster.
1685 */
1686 if (out->use_small_bufs) {
1687 compress_set_max_poll_wait(out->compr, 1000);
1688 }
1689
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001690 audio_extn_dts_create_state_notifier_node(out->usecase);
1691 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1692 popcount(out->channel_mask),
1693 out->playback_started);
1694
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001695#ifdef DS1_DOLBY_DDP_ENABLED
1696 if (audio_extn_is_dolby_format(out->format))
1697 audio_extn_dolby_send_ddp_endp_params(adev);
1698#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001699 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1700 if (adev->visualizer_start_output != NULL)
1701 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1702 if (adev->offload_effects_start_output != NULL)
1703 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001704 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001705 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001707
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001708 ALOGD("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001711error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001713error_config:
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301714 /*
1715 * sleep 50ms to allow sufficient time for kernel
1716 * drivers to recover incases like SSR.
1717 */
1718 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001719 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720}
1721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722static int check_input_parameters(uint32_t sample_rate,
1723 audio_format_t format,
1724 int channel_count)
1725{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001726 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001728 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001729 !voice_extn_compress_voip_is_format_supported(format) &&
1730 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001731
1732 switch (channel_count) {
1733 case 1:
1734 case 2:
1735 case 6:
1736 break;
1737 default:
1738 ret = -EINVAL;
1739 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740
1741 switch (sample_rate) {
1742 case 8000:
1743 case 11025:
1744 case 12000:
1745 case 16000:
1746 case 22050:
1747 case 24000:
1748 case 32000:
1749 case 44100:
1750 case 48000:
1751 break;
1752 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001753 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 }
1755
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001756 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757}
1758
1759static size_t get_input_buffer_size(uint32_t sample_rate,
1760 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001761 int channel_count,
1762 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763{
1764 size_t size = 0;
1765
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001766 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1767 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001769 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001770 if (is_low_latency)
1771 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001772 /* ToDo: should use frame_size computed based on the format and
1773 channel_count here. */
1774 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001776 /* make sure the size is multiple of 32 bytes
1777 * At 48 kHz mono 16-bit PCM:
1778 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1779 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1780 */
1781 size += 0x1f;
1782 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001783
1784 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785}
1786
1787static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1788{
1789 struct stream_out *out = (struct stream_out *)stream;
1790
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792}
1793
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001794static int out_set_sample_rate(struct audio_stream *stream __unused,
1795 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796{
1797 return -ENOSYS;
1798}
1799
1800static size_t out_get_buffer_size(const struct audio_stream *stream)
1801{
1802 struct stream_out *out = (struct stream_out *)stream;
1803
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001804 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001806 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1807 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001808
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001809 return out->config.period_size *
1810 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811}
1812
1813static uint32_t out_get_channels(const struct audio_stream *stream)
1814{
1815 struct stream_out *out = (struct stream_out *)stream;
1816
1817 return out->channel_mask;
1818}
1819
1820static audio_format_t out_get_format(const struct audio_stream *stream)
1821{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001822 struct stream_out *out = (struct stream_out *)stream;
1823
1824 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825}
1826
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001827static int out_set_format(struct audio_stream *stream __unused,
1828 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829{
1830 return -ENOSYS;
1831}
1832
1833static int out_standby(struct audio_stream *stream)
1834{
1835 struct stream_out *out = (struct stream_out *)stream;
1836 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301838 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1839 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001840 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1841 /* Ignore standby in case of voip call because the voip output
1842 * stream is closed in adev_close_output_stream()
1843 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301844 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001845 return 0;
1846 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001848 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001850 if (adev->adm_deregister_stream)
1851 adev->adm_deregister_stream(adev->adm_data, out->handle);
1852
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001853 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001855 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001856 if (out->pcm) {
1857 pcm_close(out->pcm);
1858 out->pcm = NULL;
1859 }
1860 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001861 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001862 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301863 out->send_next_track_params = false;
1864 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001865 out->gapless_mdata.encoder_delay = 0;
1866 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001867 if (out->compr != NULL) {
1868 compress_close(out->compr);
1869 out->compr = NULL;
1870 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001872 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001873 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 }
1875 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001876 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877 return 0;
1878}
1879
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001880static int out_dump(const struct audio_stream *stream __unused,
1881 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882{
1883 return 0;
1884}
1885
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001886static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1887{
1888 int ret = 0;
1889 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001890
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001892 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001893 return -EINVAL;
1894 }
1895
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301896 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001897
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001898 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1899 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301900 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001901 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001902 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1903 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301904 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001905 }
1906
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001907 ALOGV("%s new encoder delay %u and padding %u", __func__,
1908 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1909
1910 return 0;
1911}
1912
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001913static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1914{
1915 return out == adev->primary_output || out == adev->voice_tx_output;
1916}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1919{
1920 struct stream_out *out = (struct stream_out *)stream;
1921 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001922 struct audio_usecase *usecase;
1923 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 struct str_parms *parms;
1925 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001926 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001927 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928
sangwoobc677242013-08-08 16:53:43 +09001929 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301932 if (!parms)
1933 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001934 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1935 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 val = atoi(value);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001937 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001938 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301941 * When HDMI cable is unplugged/usb hs is disconnected the
1942 * music playback is paused and the policy manager sends routing=0
1943 * But the audioflingercontinues to write data until standby time
1944 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001945 * Avoid this by routing audio to speaker until standby.
1946 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301947 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1948 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001950 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1951 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001952 }
1953
1954 /*
1955 * select_devices() call below switches all the usecases on the same
1956 * backend to the new device. Refer to check_usecases_codec_backend() in
1957 * the select_devices(). But how do we undo this?
1958 *
1959 * For example, music playback is active on headset (deep-buffer usecase)
1960 * and if we go to ringtones and select a ringtone, low-latency usecase
1961 * will be started on headset+speaker. As we can't enable headset+speaker
1962 * and headset devices at the same time, select_devices() switches the music
1963 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1964 * So when the ringtone playback is completed, how do we undo the same?
1965 *
1966 * We are relying on the out_set_parameters() call on deep-buffer output,
1967 * once the ringtone playback is ended.
1968 * NOTE: We should not check if the current devices are same as new devices.
1969 * Because select_devices() must be called to switch back the music
1970 * playback to headset.
1971 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001972 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001973 out->devices = val;
1974
1975 if (!out->standby)
1976 select_devices(adev, out->usecase);
1977
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001978 if (output_drives_call(adev, out)) {
1979 if(!voice_is_in_call(adev)) {
1980 if (adev->mode == AUDIO_MODE_IN_CALL) {
1981 adev->current_call_output = out;
1982 ret = voice_start_call(adev);
1983 }
1984 } else {
1985 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001986 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001987 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001988 }
1989 }
1990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001992 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001994
1995 if (out == adev->primary_output) {
1996 pthread_mutex_lock(&adev->lock);
1997 audio_extn_set_parameters(adev, parms);
1998 pthread_mutex_unlock(&adev->lock);
1999 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002000 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002001 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002002 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002003
2004 audio_extn_dts_create_state_notifier_node(out->usecase);
2005 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2006 popcount(out->channel_mask),
2007 out->playback_started);
2008
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002009 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002010 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302013error:
Eric Laurent994a6932013-07-17 11:51:42 -07002014 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015 return ret;
2016}
2017
2018static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2019{
2020 struct stream_out *out = (struct stream_out *)stream;
2021 struct str_parms *query = str_parms_create_str(keys);
2022 char *str;
2023 char value[256];
2024 struct str_parms *reply = str_parms_create();
2025 size_t i, j;
2026 int ret;
2027 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002028
2029 if (!query || !reply) {
2030 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2031 return NULL;
2032 }
2033
Eric Laurent994a6932013-07-17 11:51:42 -07002034 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2036 if (ret >= 0) {
2037 value[0] = '\0';
2038 i = 0;
2039 while (out->supported_channel_masks[i] != 0) {
2040 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2041 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2042 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002043 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002045 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 first = false;
2047 break;
2048 }
2049 }
2050 i++;
2051 }
2052 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2053 str = str_parms_to_str(reply);
2054 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002055 voice_extn_out_get_parameters(out, query, reply);
2056 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002057 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002058 free(str);
2059 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002060 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002062
2063 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2064 if (ret >= 0) {
2065 value[0] = '\0';
2066 i = 0;
2067 first = true;
2068 while (out->supported_formats[i] != 0) {
2069 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2070 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2071 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002072 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002073 }
2074 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2075 first = false;
2076 break;
2077 }
2078 }
2079 i++;
2080 }
2081 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2082 str = str_parms_to_str(reply);
2083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084 str_parms_destroy(query);
2085 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002086 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 return str;
2088}
2089
2090static uint32_t out_get_latency(const struct audio_stream_out *stream)
2091{
2092 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002093 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094
Alexy Josephaa54c872014-12-03 02:46:47 -08002095 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002096 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002097 } else {
2098 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002100 }
2101
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302102 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002103 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104}
2105
2106static int out_set_volume(struct audio_stream_out *stream, float left,
2107 float right)
2108{
Eric Laurenta9024de2013-04-04 09:19:12 -07002109 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 int volume[2];
2111
Eric Laurenta9024de2013-04-04 09:19:12 -07002112 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2113 /* only take left channel into account: the API is for stereo anyway */
2114 out->muted = (left == 0.0f);
2115 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002116 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002117 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2118 /*
2119 * Set mute or umute on HDMI passthrough stream.
2120 * Only take left channel into account.
2121 * Mute is 0 and unmute 1
2122 */
2123 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2124 } else {
2125 char mixer_ctl_name[128];
2126 struct audio_device *adev = out->dev;
2127 struct mixer_ctl *ctl;
2128 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002129 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002131 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2132 "Compress Playback %d Volume", pcm_device_id);
2133 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2134 if (!ctl) {
2135 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2136 __func__, mixer_ctl_name);
2137 return -EINVAL;
2138 }
2139 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2140 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2141 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2142 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002144 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 return -ENOSYS;
2147}
2148
2149static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2150 size_t bytes)
2151{
2152 struct stream_out *out = (struct stream_out *)stream;
2153 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302154 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002155 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002157 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302158
Naresh Tanniru80659832014-06-04 18:17:56 +05302159 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002160 // increase written size during SSR to avoid mismatch
2161 // with the written frames count in AF
2162 if (!is_offload_usecase(out->usecase))
2163 out->written += bytes / (out->config.channels * sizeof(short));
2164
Naresh Tanniru80659832014-06-04 18:17:56 +05302165 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302166 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302167 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302168 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002169 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302170 //during SSR for compress usecase we should return error to flinger
2171 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2172 pthread_mutex_unlock(&out->lock);
2173 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302174 }
2175 }
2176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002178 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002179 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002180 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2181 ret = voice_extn_compress_voip_start_output_stream(out);
2182 else
2183 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002184 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002187 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 goto exit;
2189 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002190 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2191 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302194 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2195 setChannelStatus(out, buffer, bytes);
2196 adev->mChannelStatusSet = true;
2197 }
2198
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002199 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002200 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002201 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002202 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002203 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2204 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302205 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2206 ALOGD("copl(%p):send next track params in gapless", out);
2207 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2208 out->send_next_track_params = false;
2209 out->is_compr_metadata_avail = false;
2210 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002211 }
2212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302214 if (ret < 0)
2215 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002216 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002217 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302218 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 } else if (-ENETRESET == ret) {
2221 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2222 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2223 pthread_mutex_unlock(&out->lock);
2224 out_standby(&out->stream.common);
2225 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302227 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002229 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230 out->playback_started = 1;
2231 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002232
2233 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2234 popcount(out->channel_mask),
2235 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002236 }
2237 pthread_mutex_unlock(&out->lock);
2238 return ret;
2239 } else {
2240 if (out->pcm) {
2241 if (out->muted)
2242 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002243
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002244 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002245
2246 if (adev->adm_request_focus)
2247 adev->adm_request_focus(adev->adm_data, out->handle);
2248
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002249 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2250 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2251 else
2252 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002253
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302254 if (ret < 0)
2255 ret = -errno;
2256 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002257 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002258
2259 if (adev->adm_abandon_focus)
2260 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002261 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 }
2263
2264exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302265 /* ToDo: There may be a corner case when SSR happens back to back during
2266 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302267 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302268 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302269 }
2270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 pthread_mutex_unlock(&out->lock);
2272
2273 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002274 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002275 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302276 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302277 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302278 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302279 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302280 out->standby = true;
2281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002283 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302284 out_get_sample_rate(&out->stream.common));
2285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 }
2287 return bytes;
2288}
2289
2290static int out_get_render_position(const struct audio_stream_out *stream,
2291 uint32_t *dsp_frames)
2292{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302294 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002295
2296 if (dsp_frames == NULL)
2297 return -EINVAL;
2298
2299 *dsp_frames = 0;
2300 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002301 ssize_t ret = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002302 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002303 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302304 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302306 if (ret < 0)
2307 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002308 ALOGVV("%s rendered frames %d sample_rate %d",
2309 __func__, *dsp_frames, out->sample_rate);
2310 }
2311 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302312 if (-ENETRESET == ret) {
2313 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2314 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2315 return -EINVAL;
2316 } else if(ret < 0) {
2317 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2318 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302319 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2320 /*
2321 * Handle corner case where compress session is closed during SSR
2322 * and timestamp is queried
2323 */
2324 ALOGE(" ERROR: sound card not active, return error");
2325 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302326 } else {
2327 return 0;
2328 }
Zhou Song32a556e2015-05-05 10:46:56 +08002329 } else if (audio_is_linear_pcm(out->format)) {
2330 *dsp_frames = out->written;
2331 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 } else
2333 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334}
2335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002336static int out_add_audio_effect(const struct audio_stream *stream __unused,
2337 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002338{
2339 return 0;
2340}
2341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002342static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2343 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344{
2345 return 0;
2346}
2347
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002348static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2349 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350{
2351 return -EINVAL;
2352}
2353
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002354static int out_get_presentation_position(const struct audio_stream_out *stream,
2355 uint64_t *frames, struct timespec *timestamp)
2356{
2357 struct stream_out *out = (struct stream_out *)stream;
2358 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002359 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002360
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002361 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002362
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002363 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002364 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302365 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002366 &out->sample_rate);
2367 ALOGVV("%s rendered frames %ld sample_rate %d",
2368 __func__, dsp_frames, out->sample_rate);
2369 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302370 if (ret < 0)
2371 ret = -errno;
2372 if (-ENETRESET == ret) {
2373 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2374 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2375 ret = -EINVAL;
2376 } else
2377 ret = 0;
2378
Eric Laurent949a0892013-09-20 09:20:13 -07002379 /* this is the best we can do */
2380 clock_gettime(CLOCK_MONOTONIC, timestamp);
2381 }
2382 } else {
2383 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002384 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002385 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2386 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002387 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002388 // This adjustment accounts for buffering after app processor.
2389 // It is based on estimated DSP latency per use case, rather than exact.
2390 signed_frames -=
2391 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2392
Eric Laurent949a0892013-09-20 09:20:13 -07002393 // It would be unusual for this value to be negative, but check just in case ...
2394 if (signed_frames >= 0) {
2395 *frames = signed_frames;
2396 ret = 0;
2397 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002398 }
2399 }
2400 }
2401
2402 pthread_mutex_unlock(&out->lock);
2403
2404 return ret;
2405}
2406
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002407static int out_set_callback(struct audio_stream_out *stream,
2408 stream_callback_t callback, void *cookie)
2409{
2410 struct stream_out *out = (struct stream_out *)stream;
2411
2412 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002413 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 out->offload_callback = callback;
2415 out->offload_cookie = cookie;
2416 pthread_mutex_unlock(&out->lock);
2417 return 0;
2418}
2419
2420static int out_pause(struct audio_stream_out* stream)
2421{
2422 struct stream_out *out = (struct stream_out *)stream;
2423 int status = -ENOSYS;
2424 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002425 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002426 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002427 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302429 struct audio_device *adev = out->dev;
2430 int snd_scard_state = get_snd_card_state(adev);
2431
2432 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2433 status = compress_pause(out->compr);
2434
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002435 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002436
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302437 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002438 audio_extn_dts_notify_playback_state(out->usecase, 0,
2439 out->sample_rate, popcount(out->channel_mask),
2440 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002441 }
2442 pthread_mutex_unlock(&out->lock);
2443 }
2444 return status;
2445}
2446
2447static int out_resume(struct audio_stream_out* stream)
2448{
2449 struct stream_out *out = (struct stream_out *)stream;
2450 int status = -ENOSYS;
2451 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002452 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002453 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 status = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002455 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302457 struct audio_device *adev = out->dev;
2458 int snd_scard_state = get_snd_card_state(adev);
2459
2460 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2461 status = compress_resume(out->compr);
2462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002464
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302465 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002466 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2467 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 }
2469 pthread_mutex_unlock(&out->lock);
2470 }
2471 return status;
2472}
2473
2474static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2475{
2476 struct stream_out *out = (struct stream_out *)stream;
2477 int status = -ENOSYS;
2478 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002479 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002480 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002481 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2482 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2483 else
2484 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2485 pthread_mutex_unlock(&out->lock);
2486 }
2487 return status;
2488}
2489
2490static int out_flush(struct audio_stream_out* stream)
2491{
2492 struct stream_out *out = (struct stream_out *)stream;
2493 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002494 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002495 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002496 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 stop_compressed_output_l(out);
2498 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002499 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 return 0;
2501 }
2502 return -ENOSYS;
2503}
2504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505/** audio_stream_in implementation **/
2506static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2507{
2508 struct stream_in *in = (struct stream_in *)stream;
2509
2510 return in->config.rate;
2511}
2512
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002513static int in_set_sample_rate(struct audio_stream *stream __unused,
2514 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515{
2516 return -ENOSYS;
2517}
2518
2519static size_t in_get_buffer_size(const struct audio_stream *stream)
2520{
2521 struct stream_in *in = (struct stream_in *)stream;
2522
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002523 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2524 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002525 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2526 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002527
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002528 return in->config.period_size *
2529 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530}
2531
2532static uint32_t in_get_channels(const struct audio_stream *stream)
2533{
2534 struct stream_in *in = (struct stream_in *)stream;
2535
2536 return in->channel_mask;
2537}
2538
2539static audio_format_t in_get_format(const struct audio_stream *stream)
2540{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002541 struct stream_in *in = (struct stream_in *)stream;
2542
2543 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544}
2545
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002546static int in_set_format(struct audio_stream *stream __unused,
2547 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548{
2549 return -ENOSYS;
2550}
2551
2552static int in_standby(struct audio_stream *stream)
2553{
2554 struct stream_in *in = (struct stream_in *)stream;
2555 struct audio_device *adev = in->dev;
2556 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302557 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2558 stream, in->usecase, use_case_table[in->usecase]);
2559
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002560 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2561 /* Ignore standby in case of voip call because the voip input
2562 * stream is closed in adev_close_input_stream()
2563 */
2564 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2565 return status;
2566 }
2567
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002568 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002569 if (!in->standby && in->is_st_session) {
2570 ALOGD("%s: sound trigger pcm stop lab", __func__);
2571 audio_extn_sound_trigger_stop_lab(in);
2572 in->standby = 1;
2573 }
2574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002576 if (adev->adm_deregister_stream)
2577 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2578
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002579 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002581 if (in->pcm) {
2582 pcm_close(in->pcm);
2583 in->pcm = NULL;
2584 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002586 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 }
2588 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002589 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 return status;
2591}
2592
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002593static int in_dump(const struct audio_stream *stream __unused,
2594 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595{
2596 return 0;
2597}
2598
2599static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2600{
2601 struct stream_in *in = (struct stream_in *)stream;
2602 struct audio_device *adev = in->dev;
2603 struct str_parms *parms;
2604 char *str;
2605 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002606 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302608 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 parms = str_parms_create_str(kvpairs);
2610
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302611 if (!parms)
2612 goto error;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002613 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002614 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002615
2616 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2617 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 val = atoi(value);
2619 /* no audio source uses val == 0 */
2620 if ((in->source != val) && (val != 0)) {
2621 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002622 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2623 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2624 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2625 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002626 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002627 err = voice_extn_compress_voip_open_input_stream(in);
2628 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002629 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002630 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002631 }
2632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 }
2634 }
2635
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002636 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2637 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002639 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 in->device = val;
2641 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002642 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002643 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 }
2645 }
2646
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002647done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002649 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650
2651 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302652error:
Eric Laurent994a6932013-07-17 11:51:42 -07002653 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 return ret;
2655}
2656
2657static char* in_get_parameters(const struct audio_stream *stream,
2658 const char *keys)
2659{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002660 struct stream_in *in = (struct stream_in *)stream;
2661 struct str_parms *query = str_parms_create_str(keys);
2662 char *str;
2663 char value[256];
2664 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002665
2666 if (!query || !reply) {
2667 ALOGE("in_get_parameters: failed to create query or reply");
2668 return NULL;
2669 }
2670
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002671 ALOGV("%s: enter: keys - %s", __func__, keys);
2672
2673 voice_extn_in_get_parameters(in, query, reply);
2674
2675 str = str_parms_to_str(reply);
2676 str_parms_destroy(query);
2677 str_parms_destroy(reply);
2678
2679 ALOGV("%s: exit: returns - %s", __func__, str);
2680 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681}
2682
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002683static int in_set_gain(struct audio_stream_in *stream __unused,
2684 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685{
2686 return 0;
2687}
2688
2689static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2690 size_t bytes)
2691{
2692 struct stream_in *in = (struct stream_in *)stream;
2693 struct audio_device *adev = in->dev;
2694 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302695 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002697 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302698
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002699 if (in->is_st_session) {
2700 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2701 /* Read from sound trigger HAL */
2702 audio_extn_sound_trigger_read(in, buffer, bytes);
2703 pthread_mutex_unlock(&in->lock);
2704 return bytes;
2705 }
2706
2707 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2708 ALOGD(" %s: sound card is not active/SSR state", __func__);
2709 ret= -EIO;;
2710 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302711 }
2712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002714 pthread_mutex_lock(&adev->lock);
2715 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2716 ret = voice_extn_compress_voip_start_input_stream(in);
2717 else
2718 ret = start_input_stream(in);
2719 pthread_mutex_unlock(&adev->lock);
2720 if (ret != 0) {
2721 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 }
2723 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002724 if (adev->adm_register_input_stream)
2725 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727
Naresh Tanniru4a080142015-06-15 10:35:19 -07002728 if (adev->adm_request_focus)
2729 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002732 if (audio_extn_ssr_get_enabled() &&
2733 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002734 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002735 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2736 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002737 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2738 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002739 else
2740 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302741 if (ret < 0)
2742 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 }
2744
Naresh Tanniru4a080142015-06-15 10:35:19 -07002745 if (adev->adm_abandon_focus)
2746 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 /*
2749 * Instead of writing zeroes here, we could trust the hardware
2750 * to always provide zeroes when muted.
2751 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302752 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2753 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 memset(buffer, 0, bytes);
2755
2756exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302757 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302758 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002759 if (-ENETRESET == ret)
2760 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 pthread_mutex_unlock(&in->lock);
2763
2764 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302765 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302766 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302767 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302768 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302769 in->standby = true;
2770 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302771 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002773 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002774 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302775 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 }
2777 return bytes;
2778}
2779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002780static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781{
2782 return 0;
2783}
2784
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002785static int add_remove_audio_effect(const struct audio_stream *stream,
2786 effect_handle_t effect,
2787 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002789 struct stream_in *in = (struct stream_in *)stream;
2790 int status = 0;
2791 effect_descriptor_t desc;
2792
2793 status = (*effect)->get_descriptor(effect, &desc);
2794 if (status != 0)
2795 return status;
2796
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002797 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002798 pthread_mutex_lock(&in->dev->lock);
2799 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2800 in->enable_aec != enable &&
2801 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2802 in->enable_aec = enable;
2803 if (!in->standby)
2804 select_devices(in->dev, in->usecase);
2805 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002806 if (in->enable_ns != enable &&
2807 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2808 in->enable_ns = enable;
2809 if (!in->standby)
2810 select_devices(in->dev, in->usecase);
2811 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002812 pthread_mutex_unlock(&in->dev->lock);
2813 pthread_mutex_unlock(&in->lock);
2814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002815 return 0;
2816}
2817
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002818static int in_add_audio_effect(const struct audio_stream *stream,
2819 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820{
Eric Laurent994a6932013-07-17 11:51:42 -07002821 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002822 return add_remove_audio_effect(stream, effect, true);
2823}
2824
2825static int in_remove_audio_effect(const struct audio_stream *stream,
2826 effect_handle_t effect)
2827{
Eric Laurent994a6932013-07-17 11:51:42 -07002828 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002829 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830}
2831
2832static int adev_open_output_stream(struct audio_hw_device *dev,
2833 audio_io_handle_t handle,
2834 audio_devices_t devices,
2835 audio_output_flags_t flags,
2836 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002837 struct audio_stream_out **stream_out,
2838 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839{
2840 struct audio_device *adev = (struct audio_device *)dev;
2841 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002842 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002843 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302846
2847 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2848 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
Naresh Tanniru06f99432015-08-26 14:01:20 -07002849 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302850 return -EINVAL;
2851 }
2852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2854
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302855 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2856 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2857 devices, flags, &out->stream);
2858
2859
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002860 if (!out) {
2861 return -ENOMEM;
2862 }
2863
Haynes Mathew George204045b2015-02-25 20:32:03 -08002864 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002865 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002866 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 if (devices == AUDIO_DEVICE_NONE)
2869 devices = AUDIO_DEVICE_OUT_SPEAKER;
2870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871 out->flags = flags;
2872 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002873 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002874 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 out->sample_rate = config->sample_rate;
2876 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2877 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002878 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002879 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002880 out->non_blocking = 0;
2881 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302883 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2884 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002885 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2886 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2887
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002888 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002889 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2890 ret = read_hdmi_channel_masks(out);
2891
2892 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2893 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002894 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002895 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002896 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002897
2898 if (config->sample_rate == 0)
2899 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2900 if (config->channel_mask == 0)
2901 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2902
2903 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2906 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002908 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002910 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2911 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002912 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002913 ret = voice_extn_compress_voip_open_output_stream(out);
2914 if (ret != 0) {
2915 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2916 __func__, ret);
2917 goto error_open;
2918 }
Naresh Tanniru06f99432015-08-26 14:01:20 -07002919 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2920 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2921
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2923 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2924 ALOGE("%s: Unsupported Offload information", __func__);
2925 ret = -EINVAL;
2926 goto error_open;
2927 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002928
2929 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2930 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2931 ALOGV("read and update_pass through formats");
2932 ret = audio_extn_dolby_update_passt_formats(adev, out);
2933 if(ret != 0) {
2934 goto error_open;
2935 }
2936 if(config->offload_info.format == 0)
2937 config->offload_info.format = out->supported_formats[0];
2938 }
2939
Mingming Yin90310102013-11-13 16:57:00 -08002940 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002941 !audio_extn_is_dolby_format(config->offload_info.format)) {
Naresh Tanniru06f99432015-08-26 14:01:20 -07002942 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002943 ret = -EINVAL;
2944 goto error_open;
2945 }
2946
2947 out->compr_config.codec = (struct snd_codec *)
2948 calloc(1, sizeof(struct snd_codec));
2949
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002950 if (!out->compr_config.codec) {
2951 ret = -ENOMEM;
2952 goto error_open;
2953 }
2954
Naresh Tanniru06f99432015-08-26 14:01:20 -07002955 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2956 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2957 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2958 } else {
2959 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2960 out->usecase = get_offload_usecase(adev);
2961 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002962 if (config->offload_info.channel_mask)
2963 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002964 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002965 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002966 config->offload_info.channel_mask = config->channel_mask;
2967 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002968 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002969 out->sample_rate = config->offload_info.sample_rate;
2970
2971 out->stream.set_callback = out_set_callback;
2972 out->stream.pause = out_pause;
2973 out->stream.resume = out_resume;
2974 out->stream.drain = out_drain;
2975 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002976 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002978 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002979 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002980 audio_extn_dolby_get_snd_codec_id(adev, out,
2981 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002982 else
2983 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002984 get_snd_codec_id(config->offload_info.format);
Naresh Tanniru06f99432015-08-26 14:01:20 -07002985
2986 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2987 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002988 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002989 platform_get_pcm_offload_buffer_size(&config->offload_info);
2990 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2991 out->compr_config.fragment_size =
2992 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002993 } else {
2994 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002995 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002996 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2998 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002999 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 out->compr_config.codec->bit_rate =
3001 config->offload_info.bit_rate;
3002 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003003 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05303005 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003006 /*TODO: Do we need to change it for passthrough */
3007 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003008
Manish Dewangan93672f12015-08-24 20:30:31 +05303009 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3010 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3011 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3012 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003013 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3014 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Naresh Tanniru06f99432015-08-26 14:01:20 -07003015 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003016 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Naresh Tanniru06f99432015-08-26 14:01:20 -07003017 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3018 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003019
Mingming Yin3ee55c62014-08-04 14:23:35 -07003020 if (out->bit_width == 24) {
3021 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3022 }
3023
Amit Shekhar6f461b12014-08-01 14:52:58 -07003024 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05303025 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3028 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003029
Sharad Sangleb27354b2015-06-18 15:58:55 +05303030 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003031 //this flag is set from framework only if its for PCM formats
3032 //no need to check for PCM format again
3033 out->non_blocking = 0;
3034 out->use_small_bufs = true;
3035 ALOGI("Keep write blocking for small buff: non_blockling %d",
3036 out->non_blocking);
3037 }
3038
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003039 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05303040 out->send_next_track_params = false;
3041 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003042 out->offload_state = OFFLOAD_STATE_IDLE;
3043 out->playback_started = 0;
3044
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003045 audio_extn_dts_create_state_notifier_node(out->usecase);
3046
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 create_offload_callback_thread(out);
3048 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3049 __func__, config->offload_info.version,
3050 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003051 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003052 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003053 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3054 ret = voice_check_and_set_incall_music_usecase(adev, out);
3055 if (ret != 0) {
3056 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3057 __func__, ret);
3058 goto error_open;
3059 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003060 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3061 if (config->sample_rate == 0)
3062 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3063 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3064 config->sample_rate != 8000) {
3065 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3066 ret = -EINVAL;
3067 goto error_open;
3068 }
3069 out->sample_rate = config->sample_rate;
3070 out->config.rate = config->sample_rate;
3071 if (config->format == AUDIO_FORMAT_DEFAULT)
3072 config->format = AUDIO_FORMAT_PCM_16_BIT;
3073 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3074 config->format = AUDIO_FORMAT_PCM_16_BIT;
3075 ret = -EINVAL;
3076 goto error_open;
3077 }
3078 out->format = config->format;
3079 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3080 out->config = pcm_config_afe_proxy_playback;
3081 adev->voice_tx_output = out;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003082 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3083 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3084 out->config = pcm_config_low_latency;
3085 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003086 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003087 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3089 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003091 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3092 format = AUDIO_FORMAT_PCM_16_BIT;
3093 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3094 out->config = pcm_config_deep_buffer;
3095 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003096 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003097 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003098 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003099 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003100 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003101 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 }
3103
Amit Shekhar1d896042014-10-03 13:16:09 -07003104 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3105 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003106 /* TODO remove this hardcoding and check why width is zero*/
3107 if (out->bit_width == 0)
3108 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003109 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3110 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003111 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303112 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003113 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3114 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3115 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003116 if(adev->primary_output == NULL)
3117 adev->primary_output = out;
3118 else {
3119 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003120 ret = -EEXIST;
3121 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003122 }
3123 }
3124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 /* Check if this usecase is already existing */
3126 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003127 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3128 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003131 ret = -EEXIST;
3132 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 }
3134 pthread_mutex_unlock(&adev->lock);
3135
3136 out->stream.common.get_sample_rate = out_get_sample_rate;
3137 out->stream.common.set_sample_rate = out_set_sample_rate;
3138 out->stream.common.get_buffer_size = out_get_buffer_size;
3139 out->stream.common.get_channels = out_get_channels;
3140 out->stream.common.get_format = out_get_format;
3141 out->stream.common.set_format = out_set_format;
3142 out->stream.common.standby = out_standby;
3143 out->stream.common.dump = out_dump;
3144 out->stream.common.set_parameters = out_set_parameters;
3145 out->stream.common.get_parameters = out_get_parameters;
3146 out->stream.common.add_audio_effect = out_add_audio_effect;
3147 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3148 out->stream.get_latency = out_get_latency;
3149 out->stream.set_volume = out_set_volume;
3150 out->stream.write = out_write;
3151 out->stream.get_render_position = out_get_render_position;
3152 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003153 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003156 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003157 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158
3159 config->format = out->stream.common.get_format(&out->stream.common);
3160 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3161 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3162
3163 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303164 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
Naresh Tanniru06f99432015-08-26 14:01:20 -07003165 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003166
3167 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3168 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3169 popcount(out->channel_mask), out->playback_started);
3170
Eric Laurent994a6932013-07-17 11:51:42 -07003171 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003173
3174error_open:
3175 free(out);
3176 *stream_out = NULL;
3177 ALOGD("%s: exit: ret %d", __func__, ret);
3178 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179}
3180
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003181static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 struct audio_stream_out *stream)
3183{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003184 struct stream_out *out = (struct stream_out *)stream;
3185 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003186 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303188 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3189
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003190 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303191 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003192 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303193 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003194 if(ret != 0)
3195 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3196 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003198 out_standby(&stream->common);
3199
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003200 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003201 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003202 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003203 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003204 if (out->compr_config.codec != NULL)
3205 free(out->compr_config.codec);
3206 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003207
3208 if (adev->voice_tx_output == out)
3209 adev->voice_tx_output = NULL;
3210
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 pthread_cond_destroy(&out->cond);
3212 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003214 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215}
3216
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003217static void close_compress_sessions(struct audio_device *adev)
3218{
Mingming Yin7b762e72015-03-04 13:47:32 -08003219 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303220 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003221 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003222 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303223
3224 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003225 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303226 if (is_offload_usecase(usecase->id)) {
3227 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003228 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3229 out = usecase->stream.out;
3230 pthread_mutex_unlock(&adev->lock);
3231 out_standby(&out->stream.common);
3232 pthread_mutex_lock(&adev->lock);
3233 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303234 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003235 }
3236 pthread_mutex_unlock(&adev->lock);
3237}
3238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3240{
3241 struct audio_device *adev = (struct audio_device *)dev;
3242 struct str_parms *parms;
3243 char *str;
3244 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003245 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003246 int ret;
3247 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003249 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303252 if (!parms)
3253 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003254 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3255 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303256 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303257 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303258 struct listnode *node;
3259 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303260 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303261 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003262 //close compress sessions on OFFLINE status
3263 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303264 } else if (strstr(snd_card_status, "ONLINE")) {
3265 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303266 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303267 if (!platform_is_acdb_initialized(adev->platform)) {
3268 ret = platform_acdb_init(adev->platform);
3269 if(ret)
3270 ALOGE("acdb initialization is failed");
3271
3272 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303273 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303274 }
3275
3276 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003277 status = voice_set_parameters(adev, parms);
3278 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003279 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003281 status = platform_set_parameters(adev->platform, parms);
3282 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003283 goto done;
3284
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003285 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3286 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003287 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3289 adev->bluetooth_nrec = true;
3290 else
3291 adev->bluetooth_nrec = false;
3292 }
3293
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003294 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3295 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3297 adev->screen_off = false;
3298 else
3299 adev->screen_off = true;
3300 }
3301
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003302 ret = str_parms_get_int(parms, "rotation", &val);
3303 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003304 bool reverse_speakers = false;
3305 switch(val) {
3306 // FIXME: note that the code below assumes that the speakers are in the correct placement
3307 // relative to the user when the device is rotated 90deg from its default rotation. This
3308 // assumption is device-specific, not platform-specific like this code.
3309 case 270:
3310 reverse_speakers = true;
3311 break;
3312 case 0:
3313 case 90:
3314 case 180:
3315 break;
3316 default:
3317 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003318 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003319 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003320 if (status == 0) {
3321 if (adev->speaker_lr_swap != reverse_speakers) {
3322 adev->speaker_lr_swap = reverse_speakers;
3323 // only update the selected device if there is active pcm playback
3324 struct audio_usecase *usecase;
3325 struct listnode *node;
3326 list_for_each(node, &adev->usecase_list) {
3327 usecase = node_to_item(node, struct audio_usecase, list);
3328 if (usecase->type == PCM_PLAYBACK) {
3329 select_devices(adev, usecase->id);
3330 break;
3331 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003332 }
3333 }
3334 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003335 }
3336
Mingming Yin514a8bc2014-07-29 15:22:21 -07003337 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3338 if (ret >= 0) {
3339 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3340 adev->bt_wb_speech_enabled = true;
3341 else
3342 adev->bt_wb_speech_enabled = false;
3343 }
3344
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003345 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3346 if (ret >= 0) {
3347 val = atoi(value);
3348 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3349 ALOGV("cache new edid");
3350 platform_cache_edid(adev->platform);
3351 }
3352 }
3353
3354 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3355 if (ret >= 0) {
3356 val = atoi(value);
3357 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3358 ALOGV("invalidate cached edid");
3359 platform_invalidate_edid(adev->platform);
3360 }
3361 }
3362
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003363 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003364
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003365done:
3366 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003367 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303368error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003369 ALOGV("%s: exit with code(%d)", __func__, status);
3370 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371}
3372
3373static char* adev_get_parameters(const struct audio_hw_device *dev,
3374 const char *keys)
3375{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003376 struct audio_device *adev = (struct audio_device *)dev;
3377 struct str_parms *reply = str_parms_create();
3378 struct str_parms *query = str_parms_create_str(keys);
3379 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303380 char value[256] = {0};
3381 int ret = 0;
3382
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003383 if (!query || !reply) {
3384 ALOGE("adev_get_parameters: failed to create query or reply");
3385 return NULL;
3386 }
3387
Naresh Tannirud7205b62014-06-20 02:54:48 +05303388 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3389 sizeof(value));
3390 if (ret >=0) {
3391 int val = 1;
3392 pthread_mutex_lock(&adev->snd_card_status.lock);
3393 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3394 val = 0;
3395 pthread_mutex_unlock(&adev->snd_card_status.lock);
3396 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3397 goto exit;
3398 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003399
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003400 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003401 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003402 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003403 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303404 pthread_mutex_unlock(&adev->lock);
3405
Naresh Tannirud7205b62014-06-20 02:54:48 +05303406exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003407 str = str_parms_to_str(reply);
3408 str_parms_destroy(query);
3409 str_parms_destroy(reply);
3410
3411 ALOGV("%s: exit: returns - %s", __func__, str);
3412 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413}
3414
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003415static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416{
3417 return 0;
3418}
3419
3420static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3421{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003422 int ret;
3423 struct audio_device *adev = (struct audio_device *)dev;
3424 pthread_mutex_lock(&adev->lock);
3425 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003426 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003427 pthread_mutex_unlock(&adev->lock);
3428 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429}
3430
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003431static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3432 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433{
3434 return -ENOSYS;
3435}
3436
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003437static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3438 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439{
3440 return -ENOSYS;
3441}
3442
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003443static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3444 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445{
3446 return -ENOSYS;
3447}
3448
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003449static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3450 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451{
3452 return -ENOSYS;
3453}
3454
3455static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3456{
3457 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 pthread_mutex_lock(&adev->lock);
3460 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003461 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003463 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3464 voice_is_in_call(adev)) {
3465 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303466 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003467 adev->current_call_output = NULL;
3468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 }
3470 pthread_mutex_unlock(&adev->lock);
3471 return 0;
3472}
3473
3474static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3475{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003476 int ret;
3477
3478 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003479 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003480 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3481 pthread_mutex_unlock(&adev->lock);
3482
3483 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484}
3485
3486static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3487{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003488 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 return 0;
3490}
3491
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003492static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 const struct audio_config *config)
3494{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003495 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003497 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3498 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499}
3500
3501static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003502 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 audio_devices_t devices,
3504 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003505 struct audio_stream_in **stream_in,
3506 audio_input_flags_t flags __unused,
3507 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003508 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509{
3510 struct audio_device *adev = (struct audio_device *)dev;
3511 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003512 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003513 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003514 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 *stream_in = NULL;
3517 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3518 return -EINVAL;
3519
3520 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003521
3522 if (!in) {
3523 ALOGE("failed to allocate input stream");
3524 return -ENOMEM;
3525 }
3526
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303527 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003528 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3529 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003531 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07003532 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 in->stream.common.get_sample_rate = in_get_sample_rate;
3535 in->stream.common.set_sample_rate = in_set_sample_rate;
3536 in->stream.common.get_buffer_size = in_get_buffer_size;
3537 in->stream.common.get_channels = in_get_channels;
3538 in->stream.common.get_format = in_get_format;
3539 in->stream.common.set_format = in_set_format;
3540 in->stream.common.standby = in_standby;
3541 in->stream.common.dump = in_dump;
3542 in->stream.common.set_parameters = in_set_parameters;
3543 in->stream.common.get_parameters = in_get_parameters;
3544 in->stream.common.add_audio_effect = in_add_audio_effect;
3545 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3546 in->stream.set_gain = in_set_gain;
3547 in->stream.read = in_read;
3548 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3549
3550 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003551 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 in->standby = 1;
3554 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003555 in->capture_handle = handle;
Naresh Tanniru4a080142015-06-15 10:35:19 -07003556 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557
3558 /* Update config params with the requested sample rate and channels */
3559 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003560 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3561 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3562 is_low_latency = true;
3563#if LOW_LATENCY_CAPTURE_USE_CASE
3564 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3565#endif
3566 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003568 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003569 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003571 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303572 if (adev->mode != AUDIO_MODE_IN_CALL) {
3573 ret = -EINVAL;
3574 goto err_open;
3575 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003576 if (config->sample_rate == 0)
3577 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3578 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3579 config->sample_rate != 8000) {
3580 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3581 ret = -EINVAL;
3582 goto err_open;
3583 }
3584 if (config->format == AUDIO_FORMAT_DEFAULT)
3585 config->format = AUDIO_FORMAT_PCM_16_BIT;
3586 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3587 config->format = AUDIO_FORMAT_PCM_16_BIT;
3588 ret = -EINVAL;
3589 goto err_open;
3590 }
3591
3592 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3593 in->config = pcm_config_afe_proxy_record;
3594 in->config.channels = channel_count;
3595 in->config.rate = config->sample_rate;
3596 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003597 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003598 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003599 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3600 ret = -EINVAL;
3601 goto err_open;
3602 }
3603 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003604 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003605 }
Mingming Yine62d7842013-10-25 16:26:03 -07003606 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003607 audio_extn_compr_cap_format_supported(config->format) &&
3608 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003609 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003610 } else {
3611 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003612 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003613 buffer_size = get_input_buffer_size(config->sample_rate,
3614 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003615 channel_count,
3616 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003617 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003618 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3619 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3620 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3621 (in->config.rate == 8000 || in->config.rate == 16000) &&
3622 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3623 voice_extn_compress_voip_open_input_stream(in);
3624 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003625 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003627 /* This stream could be for sound trigger lab,
3628 get sound trigger pcm if present */
3629 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303630 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003633 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635
3636err_open:
3637 free(in);
3638 *stream_in = NULL;
3639 return ret;
3640}
3641
3642static void adev_close_input_stream(struct audio_hw_device *dev,
3643 struct audio_stream_in *stream)
3644{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003645 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003646 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003647 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303648
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303649 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003650
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303651 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003652 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303653
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003654 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303655 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003656 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303657 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003658 if (ret != 0)
3659 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3660 __func__, ret);
3661 } else
3662 in_standby(&stream->common);
3663
Mingming Yin7b762e72015-03-04 13:47:32 -08003664 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003665 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003666 audio_extn_ssr_deinit();
3667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668
Mingming Yine62d7842013-10-25 16:26:03 -07003669 if(audio_extn_compr_cap_enabled() &&
3670 audio_extn_compr_cap_format_supported(in->config.format))
3671 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003672
3673 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 return;
3675}
3676
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003677static int adev_dump(const audio_hw_device_t *device __unused,
3678 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679{
3680 return 0;
3681}
3682
3683static int adev_close(hw_device_t *device)
3684{
3685 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003686
3687 if (!adev)
3688 return 0;
3689
3690 pthread_mutex_lock(&adev_init_lock);
3691
3692 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003693 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003694 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003695 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003696 audio_route_free(adev->audio_route);
3697 free(adev->snd_dev_ref_cnt);
3698 platform_deinit(adev->platform);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003699 if (adev->adm_deinit)
3700 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003701 free(device);
3702 adev = NULL;
3703 }
3704 pthread_mutex_unlock(&adev_init_lock);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 return 0;
3707}
3708
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003709/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3710 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3711 * just that it _might_ work.
3712 */
3713static int period_size_is_plausible_for_low_latency(int period_size)
3714{
3715 switch (period_size) {
3716 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003717 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003718 case 240:
3719 case 320:
3720 case 480:
3721 return 1;
3722 default:
3723 return 0;
3724 }
3725}
3726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727static int adev_open(const hw_module_t *module, const char *name,
3728 hw_device_t **device)
3729{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003730 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003732 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3734
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003735 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003736 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003737 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003738 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003739 ALOGD("%s: returning existing instance of adev", __func__);
3740 ALOGD("%s: exit", __func__);
3741 pthread_mutex_unlock(&adev_init_lock);
3742 return 0;
3743 }
3744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 adev = calloc(1, sizeof(struct audio_device));
3746
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003747 if (!adev) {
3748 pthread_mutex_unlock(&adev_init_lock);
3749 return -ENOMEM;
3750 }
3751
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003752 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3755 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3756 adev->device.common.module = (struct hw_module_t *)module;
3757 adev->device.common.close = adev_close;
3758
3759 adev->device.init_check = adev_init_check;
3760 adev->device.set_voice_volume = adev_set_voice_volume;
3761 adev->device.set_master_volume = adev_set_master_volume;
3762 adev->device.get_master_volume = adev_get_master_volume;
3763 adev->device.set_master_mute = adev_set_master_mute;
3764 adev->device.get_master_mute = adev_get_master_mute;
3765 adev->device.set_mode = adev_set_mode;
3766 adev->device.set_mic_mute = adev_set_mic_mute;
3767 adev->device.get_mic_mute = adev_get_mic_mute;
3768 adev->device.set_parameters = adev_set_parameters;
3769 adev->device.get_parameters = adev_get_parameters;
3770 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3771 adev->device.open_output_stream = adev_open_output_stream;
3772 adev->device.close_output_stream = adev_close_output_stream;
3773 adev->device.open_input_stream = adev_open_input_stream;
3774 adev->device.close_input_stream = adev_close_input_stream;
3775 adev->device.dump = adev_dump;
3776
3777 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003779 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003780 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003783 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003784 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003785 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003786 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003787 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003788 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003789 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303790 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303791
3792 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3793 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003795 adev->platform = platform_init(adev);
3796 if (!adev->platform) {
3797 free(adev->snd_dev_ref_cnt);
3798 free(adev);
3799 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3800 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003801 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003802 return -EINVAL;
3803 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003804
Naresh Tanniru4c630392014-05-12 01:05:52 +05303805 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3806
Eric Laurentc4aef752013-09-12 17:45:53 -07003807 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3808 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3809 if (adev->visualizer_lib == NULL) {
3810 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3811 } else {
3812 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3813 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003814 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003815 "visualizer_hal_start_output");
3816 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003817 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003818 "visualizer_hal_stop_output");
3819 }
3820 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003821 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003822 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003823
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003824 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3825 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3826 if (adev->offload_effects_lib == NULL) {
3827 ALOGE("%s: DLOPEN failed for %s", __func__,
3828 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3829 } else {
3830 ALOGV("%s: DLOPEN successful for %s", __func__,
3831 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3832 adev->offload_effects_start_output =
3833 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3834 "offload_effects_bundle_hal_start_output");
3835 adev->offload_effects_stop_output =
3836 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3837 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003838 adev->offload_effects_set_hpx_state =
3839 (int (*)(bool))dlsym(adev->offload_effects_lib,
3840 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303841 adev->offload_effects_get_parameters =
3842 (void (*)(struct str_parms *, struct str_parms *))
3843 dlsym(adev->offload_effects_lib,
3844 "offload_effects_bundle_get_parameters");
3845 adev->offload_effects_set_parameters =
3846 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3847 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003848 }
3849 }
3850
Naresh Tanniru4a080142015-06-15 10:35:19 -07003851 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3852 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3853 if (adev->adm_lib == NULL) {
3854 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3855 } else {
3856 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3857 adev->adm_init = (adm_init_t)
3858 dlsym(adev->adm_lib, "adm_init");
3859 adev->adm_deinit = (adm_deinit_t)
3860 dlsym(adev->adm_lib, "adm_deinit");
3861 adev->adm_register_input_stream = (adm_register_input_stream_t)
3862 dlsym(adev->adm_lib, "adm_register_input_stream");
3863 adev->adm_register_output_stream = (adm_register_output_stream_t)
3864 dlsym(adev->adm_lib, "adm_register_output_stream");
3865 adev->adm_deregister_stream = (adm_deregister_stream_t)
3866 dlsym(adev->adm_lib, "adm_deregister_stream");
3867 adev->adm_request_focus = (adm_request_focus_t)
3868 dlsym(adev->adm_lib, "adm_request_focus");
3869 adev->adm_abandon_focus = (adm_abandon_focus_t)
3870 dlsym(adev->adm_lib, "adm_abandon_focus");
3871 }
3872 }
3873
Mingming Yin514a8bc2014-07-29 15:22:21 -07003874 adev->bt_wb_speech_enabled = false;
3875
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003876 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 *device = &adev->device.common;
3878
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003879 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3880 &adev->streams_output_cfg_list);
3881
Kiran Kandi910e1862013-10-29 13:29:42 -07003882 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003883
3884 char value[PROPERTY_VALUE_MAX];
3885 int trial;
3886 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3887 trial = atoi(value);
3888 if (period_size_is_plausible_for_low_latency(trial)) {
3889 pcm_config_low_latency.period_size = trial;
3890 pcm_config_low_latency.start_threshold = trial / 4;
3891 pcm_config_low_latency.avail_min = trial / 4;
3892 configured_low_latency_capture_period_size = trial;
3893 }
3894 }
3895 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3896 trial = atoi(value);
3897 if (period_size_is_plausible_for_low_latency(trial)) {
3898 configured_low_latency_capture_period_size = trial;
3899 }
3900 }
3901
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003902 pthread_mutex_unlock(&adev_init_lock);
3903
Naresh Tanniru4a080142015-06-15 10:35:19 -07003904 if (adev->adm_init)
3905 adev->adm_data = adev->adm_init();
3906
Eric Laurent994a6932013-07-17 11:51:42 -07003907 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 return 0;
3909}
3910
3911static struct hw_module_methods_t hal_module_methods = {
3912 .open = adev_open,
3913};
3914
3915struct audio_module HAL_MODULE_INFO_SYM = {
3916 .common = {
3917 .tag = HARDWARE_MODULE_TAG,
3918 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3919 .hal_api_version = HARDWARE_HAL_API_VERSION,
3920 .id = AUDIO_HARDWARE_MODULE_ID,
3921 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003922 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 .methods = &hal_module_methods,
3924 },
3925};