blob: 6af23f12a8496e77ce7518bc30e0cce2bae7dbd4 [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) {
Pavan Chikkalab76ed862015-09-12 18:29:02 +0530918 audio_extn_dolby_set_endpoint(adev);
919 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920 return 0;
921 }
922
sangwoobc677242013-08-08 16:53:43 +0900923 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700924 out_snd_device, platform_get_snd_device_name(out_snd_device),
925 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927 /*
928 * Limitation: While in call, to do a device switch we need to disable
929 * and enable both RX and TX devices though one of them is same as current
930 * device.
931 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700932 if ((usecase->type == VOICE_CALL) &&
933 (usecase->in_snd_device != SND_DEVICE_NONE) &&
934 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700935 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700936 }
937
938 if (((usecase->type == VOICE_CALL) ||
939 (usecase->type == VOIP_CALL)) &&
940 (usecase->out_snd_device != SND_DEVICE_NONE)) {
941 /* Disable sidetone only if voice/voip call already exists */
942 if (voice_is_call_state_active(adev) ||
943 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700944 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800945 }
946
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 /* Disable current sound devices */
948 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 disable_audio_route(adev, usecase);
950 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951 }
952
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700954 disable_audio_route(adev, usecase);
955 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956 }
957
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800958 /* Applicable only on the targets that has external modem.
959 * New device information should be sent to modem before enabling
960 * the devices to reduce in-call device switch time.
961 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700962 if ((usecase->type == VOICE_CALL) &&
963 (usecase->in_snd_device != SND_DEVICE_NONE) &&
964 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800965 status = platform_switch_voice_call_enable_device_config(adev->platform,
966 out_snd_device,
967 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700968 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800969
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 /* Enable new sound devices */
971 if (out_snd_device != SND_DEVICE_NONE) {
972 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
973 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700974 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975 }
976
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700977 if (in_snd_device != SND_DEVICE_NONE) {
978 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700979 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700980 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981
Avinash Vaish71a8b972014-07-24 15:36:33 +0530982 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700983 status = platform_switch_voice_call_device_post(adev->platform,
984 out_snd_device,
985 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530986 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella884fa882015-08-14 18:00:08 -0700987 /* Enable sidetone only if voice/voip call already exists */
988 if (voice_is_call_state_active(adev) ||
989 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700990 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530991 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800992
sangwoo170731f2013-06-08 15:36:36 +0900993 usecase->in_snd_device = in_snd_device;
994 usecase->out_snd_device = out_snd_device;
995
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530996 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700997 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530998 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700999 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301000 usecase->stream.out->flags,
1001 usecase->stream.out->format,
1002 usecase->stream.out->sample_rate,
1003 usecase->stream.out->bit_width,
1004 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001005 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301006 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001007
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001008 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001009
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001010 /* Applicable only on the targets that has external modem.
1011 * Enable device command should be sent to modem only after
1012 * enabling voice call mixer controls
1013 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001014 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001015 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1016 out_snd_device,
1017 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301018 ALOGD("%s: done",__func__);
1019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 return status;
1021}
1022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023static int stop_input_stream(struct stream_in *in)
1024{
1025 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026 struct audio_usecase *uc_info;
1027 struct audio_device *adev = in->dev;
1028
Eric Laurentc8400632013-02-14 19:04:54 -08001029 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030
Eric Laurent994a6932013-07-17 11:51:42 -07001031 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 uc_info = get_usecase_from_list(adev, in->usecase);
1034 if (uc_info == NULL) {
1035 ALOGE("%s: Could not find the usecase (%d) in the list",
1036 __func__, in->usecase);
1037 return -EINVAL;
1038 }
1039
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001040 /* Close in-call recording streams */
1041 voice_check_and_stop_incall_rec_usecase(adev, in);
1042
Eric Laurent150dbfe2013-02-27 14:31:02 -08001043 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001044 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001045
1046 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001047 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001049 list_remove(&uc_info->list);
1050 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051
Eric Laurent994a6932013-07-17 11:51:42 -07001052 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053 return ret;
1054}
1055
1056int start_input_stream(struct stream_in *in)
1057{
1058 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001059 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 struct audio_usecase *uc_info;
1061 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301062 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301064 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1065 if (get_usecase_from_list(adev, usecase) == NULL)
1066 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301067 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1068 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001069
Naresh Tanniru80659832014-06-04 18:17:56 +05301070
1071 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301072 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301073 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301074 goto error_config;
1075 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301076
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001077 /* Check if source matches incall recording usecase criteria */
1078 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1079 if (ret)
1080 goto error_config;
1081 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301082 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1083
1084 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1085 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1086 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1087 goto error_config;
1088 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001089
Eric Laurentb23d5282013-05-14 15:27:20 -07001090 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 if (in->pcm_device_id < 0) {
1092 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1093 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001094 ret = -EINVAL;
1095 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001097
1098 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001100
1101 if (!uc_info) {
1102 ret = -ENOMEM;
1103 goto error_config;
1104 }
1105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106 uc_info->id = in->usecase;
1107 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001108 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001109 uc_info->devices = in->device;
1110 uc_info->in_snd_device = SND_DEVICE_NONE;
1111 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001113 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301114 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116
Eric Laurentc8400632013-02-14 19:04:54 -08001117 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001118 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1119
1120 unsigned int flags = PCM_IN;
1121 unsigned int pcm_open_retry_count = 0;
1122
1123 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1124 flags |= PCM_MMAP | PCM_NOIRQ;
1125 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1126 }
1127
1128 while (1) {
1129 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1130 flags, &in->config);
1131 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1132 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1133 if (in->pcm != NULL) {
1134 pcm_close(in->pcm);
1135 in->pcm = NULL;
1136 }
1137 if (pcm_open_retry_count-- == 0) {
1138 ret = -EIO;
1139 goto error_open;
1140 }
1141 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1142 continue;
1143 }
1144 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001145 }
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001146
1147 ALOGV("%s: pcm_prepare", __func__);
1148 ret = pcm_prepare(in->pcm);
1149 if (ret < 0) {
1150 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1151 pcm_close(in->pcm);
1152 in->pcm = NULL;
1153 goto error_open;
1154 }
1155
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301156 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301157
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001158 ALOGD("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001159
Eric Laurentc8400632013-02-14 19:04:54 -08001160 return ret;
1161
1162error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001163 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301164 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001165
1166error_config:
1167 adev->active_input = NULL;
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301168 /*
1169 * sleep 50ms to allow sufficient time for kernel
1170 * drivers to recover incases like SSR.
1171 */
1172 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001174
1175 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176}
1177
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001178void lock_input_stream(struct stream_in *in)
1179{
1180 pthread_mutex_lock(&in->pre_lock);
1181 pthread_mutex_lock(&in->lock);
1182 pthread_mutex_unlock(&in->pre_lock);
1183}
1184
1185void lock_output_stream(struct stream_out *out)
1186{
1187 pthread_mutex_lock(&out->pre_lock);
1188 pthread_mutex_lock(&out->lock);
1189 pthread_mutex_unlock(&out->pre_lock);
1190}
1191
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001192/* must be called with out->lock locked */
1193static int send_offload_cmd_l(struct stream_out* out, int command)
1194{
1195 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1196
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001197 if (!cmd) {
1198 ALOGE("failed to allocate mem for command 0x%x", command);
1199 return -ENOMEM;
1200 }
1201
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001202 ALOGVV("%s %d", __func__, command);
1203
1204 cmd->cmd = command;
1205 list_add_tail(&out->offload_cmd_list, &cmd->node);
1206 pthread_cond_signal(&out->offload_cond);
1207 return 0;
1208}
1209
1210/* must be called iwth out->lock locked */
1211static void stop_compressed_output_l(struct stream_out *out)
1212{
1213 out->offload_state = OFFLOAD_STATE_IDLE;
1214 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001215 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001216 if (out->compr != NULL) {
1217 compress_stop(out->compr);
1218 while (out->offload_thread_blocked) {
1219 pthread_cond_wait(&out->cond, &out->lock);
1220 }
1221 }
1222}
1223
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001224bool is_offload_usecase(audio_usecase_t uc_id)
1225{
1226 unsigned int i;
1227 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1228 if (uc_id == offload_usecases[i])
1229 return true;
1230 }
1231 return false;
1232}
1233
1234static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1235{
1236 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1237 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1238 char value[PROPERTY_VALUE_MAX] = {0};
1239
1240 property_get("audio.offload.multiple.enabled", value, NULL);
1241 if (!(atoi(value) || !strncmp("true", value, 4)))
1242 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1243
1244 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1245 for (i = 0; i < num_usecase; i++) {
1246 if (!(adev->offload_usecases_state & (0x1<<i))) {
1247 adev->offload_usecases_state |= 0x1 << i;
1248 ret = offload_usecases[i];
1249 break;
1250 }
1251 }
1252 ALOGV("%s: offload usecase is %d", __func__, ret);
1253 return ret;
1254}
1255
1256static void free_offload_usecase(struct audio_device *adev,
1257 audio_usecase_t uc_id)
1258{
1259 unsigned int i;
1260 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1261 if (offload_usecases[i] == uc_id) {
1262 adev->offload_usecases_state &= ~(0x1<<i);
1263 break;
1264 }
1265 }
1266 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1267}
1268
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001269static void *offload_thread_loop(void *context)
1270{
1271 struct stream_out *out = (struct stream_out *) context;
1272 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001273 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001274
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001275 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1276 set_sched_policy(0, SP_FOREGROUND);
1277 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1278
1279 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001280 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001281 for (;;) {
1282 struct offload_cmd *cmd = NULL;
1283 stream_callback_event_t event;
1284 bool send_callback = false;
1285
1286 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1287 __func__, list_empty(&out->offload_cmd_list),
1288 out->offload_state);
1289 if (list_empty(&out->offload_cmd_list)) {
1290 ALOGV("%s SLEEPING", __func__);
1291 pthread_cond_wait(&out->offload_cond, &out->lock);
1292 ALOGV("%s RUNNING", __func__);
1293 continue;
1294 }
1295
1296 item = list_head(&out->offload_cmd_list);
1297 cmd = node_to_item(item, struct offload_cmd, node);
1298 list_remove(item);
1299
1300 ALOGVV("%s STATE %d CMD %d out->compr %p",
1301 __func__, out->offload_state, cmd->cmd, out->compr);
1302
1303 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1304 free(cmd);
1305 break;
1306 }
1307
1308 if (out->compr == NULL) {
1309 ALOGE("%s: Compress handle is NULL", __func__);
1310 pthread_cond_signal(&out->cond);
1311 continue;
1312 }
1313 out->offload_thread_blocked = true;
1314 pthread_mutex_unlock(&out->lock);
1315 send_callback = false;
1316 switch(cmd->cmd) {
1317 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001318 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001320 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001321 send_callback = true;
1322 event = STREAM_CBK_EVENT_WRITE_READY;
1323 break;
1324 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001325 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301326 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001327 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301328 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001329 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301330 if (ret < 0)
1331 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301332 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301333 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001334 compress_drain(out->compr);
1335 else
1336 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301337 if (ret != -ENETRESET) {
1338 send_callback = true;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301339 pthread_mutex_lock(&out->lock);
1340 out->send_new_metadata = 1;
1341 out->send_next_track_params = true;
1342 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301343 event = STREAM_CBK_EVENT_DRAIN_READY;
1344 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1345 } else
1346 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001347 break;
1348 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001349 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001350 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001351 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001352 send_callback = true;
1353 event = STREAM_CBK_EVENT_DRAIN_READY;
1354 break;
1355 default:
1356 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1357 break;
1358 }
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001359 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001360 out->offload_thread_blocked = false;
1361 pthread_cond_signal(&out->cond);
vivek mehtacc70d4b2015-09-25 14:07:43 -07001362 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001363 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001364 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001365 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001366 free(cmd);
1367 }
1368
1369 pthread_cond_signal(&out->cond);
1370 while (!list_empty(&out->offload_cmd_list)) {
1371 item = list_head(&out->offload_cmd_list);
1372 list_remove(item);
1373 free(node_to_item(item, struct offload_cmd, node));
1374 }
1375 pthread_mutex_unlock(&out->lock);
1376
1377 return NULL;
1378}
1379
1380static int create_offload_callback_thread(struct stream_out *out)
1381{
1382 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1383 list_init(&out->offload_cmd_list);
1384 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1385 offload_thread_loop, out);
1386 return 0;
1387}
1388
1389static int destroy_offload_callback_thread(struct stream_out *out)
1390{
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001391 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001392 stop_compressed_output_l(out);
1393 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1394
1395 pthread_mutex_unlock(&out->lock);
1396 pthread_join(out->offload_thread, (void **) NULL);
1397 pthread_cond_destroy(&out->offload_cond);
1398
1399 return 0;
1400}
1401
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402static bool allow_hdmi_channel_config(struct audio_device *adev)
1403{
1404 struct listnode *node;
1405 struct audio_usecase *usecase;
1406 bool ret = true;
1407
1408 list_for_each(node, &adev->usecase_list) {
1409 usecase = node_to_item(node, struct audio_usecase, list);
1410 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1411 /*
1412 * If voice call is already existing, do not proceed further to avoid
1413 * disabling/enabling both RX and TX devices, CSD calls, etc.
1414 * Once the voice call done, the HDMI channels can be configured to
1415 * max channels of remaining use cases.
1416 */
1417 if (usecase->id == USECASE_VOICE_CALL) {
1418 ALOGD("%s: voice call is active, no change in HDMI channels",
1419 __func__);
1420 ret = false;
1421 break;
1422 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1423 ALOGD("%s: multi channel playback is active, "
1424 "no change in HDMI channels", __func__);
1425 ret = false;
1426 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001427 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001428 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001429 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1430 ", no change in HDMI channels", __func__,
1431 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001432 ret = false;
1433 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001434 }
1435 }
1436 }
1437 return ret;
1438}
1439
1440static int check_and_set_hdmi_channels(struct audio_device *adev,
1441 unsigned int channels)
1442{
1443 struct listnode *node;
1444 struct audio_usecase *usecase;
1445
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001446 unsigned int supported_channels = platform_edid_get_max_channels(
1447 adev->platform);
1448 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001449 /* Check if change in HDMI channel config is allowed */
1450 if (!allow_hdmi_channel_config(adev))
1451 return 0;
1452
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001453 if (channels > supported_channels)
1454 channels = supported_channels;
1455
Eric Laurent07eeafd2013-10-06 12:52:49 -07001456 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001457 ALOGD("%s: Requested channels are same as current channels(%d)",
1458 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001459 return 0;
1460 }
1461
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001462 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001463 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001464 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001465 adev->cur_hdmi_channels = channels;
1466
1467 /*
1468 * Deroute all the playback streams routed to HDMI so that
1469 * the back end is deactivated. Note that backend will not
1470 * be deactivated if any one stream is connected to it.
1471 */
1472 list_for_each(node, &adev->usecase_list) {
1473 usecase = node_to_item(node, struct audio_usecase, list);
1474 if (usecase->type == PCM_PLAYBACK &&
1475 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001476 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001477 }
1478 }
1479
1480 /*
1481 * Enable all the streams disabled above. Now the HDMI backend
1482 * will be activated with new channel configuration
1483 */
1484 list_for_each(node, &adev->usecase_list) {
1485 usecase = node_to_item(node, struct audio_usecase, list);
1486 if (usecase->type == PCM_PLAYBACK &&
1487 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001488 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001489 }
1490 }
1491
1492 return 0;
1493}
1494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495static int stop_output_stream(struct stream_out *out)
1496{
1497 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 struct audio_usecase *uc_info;
1499 struct audio_device *adev = out->dev;
1500
Eric Laurent994a6932013-07-17 11:51:42 -07001501 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503 uc_info = get_usecase_from_list(adev, out->usecase);
1504 if (uc_info == NULL) {
1505 ALOGE("%s: Could not find the usecase (%d) in the list",
1506 __func__, out->usecase);
1507 return -EINVAL;
1508 }
1509
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001510 if (is_offload_usecase(out->usecase) &&
1511 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001512 if (adev->visualizer_stop_output != NULL)
1513 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001514
1515 audio_extn_dts_remove_state_notifier_node(out->usecase);
1516
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001517 if (adev->offload_effects_stop_output != NULL)
1518 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1519 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001520
Eric Laurent150dbfe2013-02-27 14:31:02 -08001521 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001522 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523
1524 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001525 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001527 list_remove(&uc_info->list);
1528 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001530 if (is_offload_usecase(out->usecase) &&
1531 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1532 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1533 ALOGV("Disable passthrough , reset mixer to pcm");
1534 /* NO_PASSTHROUGH */
1535 out->compr_config.codec->compr_passthr = 0;
1536 audio_extn_dolby_set_hdmi_config(adev, out);
1537 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1538 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001539 /* Must be called after removing the usecase from list */
1540 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1541 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1542
Eric Laurent994a6932013-07-17 11:51:42 -07001543 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 return ret;
1545}
1546
1547int start_output_stream(struct stream_out *out)
1548{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001550 int sink_channels = 0;
1551 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 struct audio_usecase *uc_info;
1553 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301554 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001556 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1557 ret = -EINVAL;
1558 goto error_config;
1559 }
1560
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301561 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1562 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1563 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301564
Naresh Tanniru80659832014-06-04 18:17:56 +05301565 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301566 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301567 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301568 goto error_config;
1569 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301570
Eric Laurentb23d5282013-05-14 15:27:20 -07001571 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 if (out->pcm_device_id < 0) {
1573 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1574 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001575 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001576 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 }
1578
1579 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001580
1581 if (!uc_info) {
1582 ret = -ENOMEM;
1583 goto error_config;
1584 }
1585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 uc_info->id = out->usecase;
1587 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001588 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 uc_info->devices = out->devices;
1590 uc_info->in_snd_device = SND_DEVICE_NONE;
1591 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001592 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001593 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001594 if (is_offload_usecase(out->usecase)) {
1595 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001596 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1597 }
1598 }
Mingming Yin9c041392014-05-01 15:37:31 -07001599 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1600 if (!strncmp("true", prop_value, 4)) {
1601 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001602 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1603 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001604 check_and_set_hdmi_channels(adev, sink_channels);
1605 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001606 if (is_offload_usecase(out->usecase)) {
1607 unsigned int ch_count = out->compr_config.codec->ch_in;
1608 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1609 /* backend channel config for passthrough stream is stereo */
1610 ch_count = 2;
1611 check_and_set_hdmi_channels(adev, ch_count);
1612 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001613 check_and_set_hdmi_channels(adev, out->config.channels);
1614 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001615 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001616 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001617 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 select_devices(adev, out->usecase);
1620
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001621 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1622 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001623 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001624 unsigned int flags = PCM_OUT;
1625 unsigned int pcm_open_retry_count = 0;
1626 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1627 flags |= PCM_MMAP | PCM_NOIRQ;
1628 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1629 } else
1630 flags |= PCM_MONOTONIC;
1631
1632 while (1) {
1633 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1634 flags, &out->config);
1635 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1636 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1637 if (out->pcm != NULL) {
1638 pcm_close(out->pcm);
1639 out->pcm = NULL;
1640 }
1641 if (pcm_open_retry_count-- == 0) {
1642 ret = -EIO;
1643 goto error_open;
1644 }
1645 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1646 continue;
1647 }
1648 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001649 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001650
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001651 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1652 out->pcm_device_id);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001653
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001654 ALOGV("%s: pcm_prepare", __func__);
1655 if (pcm_is_ready(out->pcm)) {
1656 ret = pcm_prepare(out->pcm);
1657 if (ret < 0) {
1658 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1659 pcm_close(out->pcm);
1660 out->pcm = NULL;
1661 goto error_open;
1662 }
1663 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001664 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001665 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1666 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001668 out->compr = compress_open(adev->snd_card,
1669 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 COMPRESS_IN, &out->compr_config);
1671 if (out->compr && !is_compress_ready(out->compr)) {
1672 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1673 compress_close(out->compr);
1674 out->compr = NULL;
1675 ret = -EIO;
1676 goto error_open;
1677 }
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301678 /* compress_open sends params of the track, so reset the flag here */
1679 out->is_compr_metadata_avail = false;
1680
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 if (out->offload_callback)
1682 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001683
Fred Oh3f43e742015-03-04 18:42:34 -08001684 /* Since small bufs uses blocking writes, a write will be blocked
1685 for the default max poll time (20s) in the event of an SSR.
1686 Reduce the poll time to observe and deal with SSR faster.
1687 */
1688 if (out->use_small_bufs) {
1689 compress_set_max_poll_wait(out->compr, 1000);
1690 }
1691
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001692 audio_extn_dts_create_state_notifier_node(out->usecase);
1693 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1694 popcount(out->channel_mask),
1695 out->playback_started);
1696
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001697#ifdef DS1_DOLBY_DDP_ENABLED
1698 if (audio_extn_is_dolby_format(out->format))
1699 audio_extn_dolby_send_ddp_endp_params(adev);
1700#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001701 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1702 if (adev->visualizer_start_output != NULL)
1703 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1704 if (adev->offload_effects_start_output != NULL)
1705 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001706 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001707 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07001709
Ravi Kumar Alamanda14c57d82015-09-30 22:27:26 -07001710 ALOGD("%s: exit", __func__);
Naresh Tanniru4a080142015-06-15 10:35:19 -07001711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001715error_config:
Laxminath Kasam515f5d42015-09-24 03:59:15 +05301716 /*
1717 * sleep 50ms to allow sufficient time for kernel
1718 * drivers to recover incases like SSR.
1719 */
1720 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001721 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722}
1723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724static int check_input_parameters(uint32_t sample_rate,
1725 audio_format_t format,
1726 int channel_count)
1727{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001728 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001730 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001731 !voice_extn_compress_voip_is_format_supported(format) &&
1732 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001733
1734 switch (channel_count) {
1735 case 1:
1736 case 2:
1737 case 6:
1738 break;
1739 default:
1740 ret = -EINVAL;
1741 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742
1743 switch (sample_rate) {
1744 case 8000:
1745 case 11025:
1746 case 12000:
1747 case 16000:
1748 case 22050:
1749 case 24000:
1750 case 32000:
1751 case 44100:
1752 case 48000:
1753 break;
1754 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001755 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756 }
1757
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001758 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759}
1760
1761static size_t get_input_buffer_size(uint32_t sample_rate,
1762 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001763 int channel_count,
1764 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765{
1766 size_t size = 0;
1767
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001768 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1769 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001771 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001772 if (is_low_latency)
1773 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001774 /* ToDo: should use frame_size computed based on the format and
1775 channel_count here. */
1776 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001778 /* make sure the size is multiple of 32 bytes
1779 * At 48 kHz mono 16-bit PCM:
1780 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1781 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1782 */
1783 size += 0x1f;
1784 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001785
1786 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787}
1788
1789static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1790{
1791 struct stream_out *out = (struct stream_out *)stream;
1792
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794}
1795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001796static int out_set_sample_rate(struct audio_stream *stream __unused,
1797 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798{
1799 return -ENOSYS;
1800}
1801
1802static size_t out_get_buffer_size(const struct audio_stream *stream)
1803{
1804 struct stream_out *out = (struct stream_out *)stream;
1805
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001806 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001808 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1809 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001810
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001811 return out->config.period_size *
1812 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813}
1814
1815static uint32_t out_get_channels(const struct audio_stream *stream)
1816{
1817 struct stream_out *out = (struct stream_out *)stream;
1818
1819 return out->channel_mask;
1820}
1821
1822static audio_format_t out_get_format(const struct audio_stream *stream)
1823{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 struct stream_out *out = (struct stream_out *)stream;
1825
1826 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827}
1828
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001829static int out_set_format(struct audio_stream *stream __unused,
1830 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831{
1832 return -ENOSYS;
1833}
1834
1835static int out_standby(struct audio_stream *stream)
1836{
1837 struct stream_out *out = (struct stream_out *)stream;
1838 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301840 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1841 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001842 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1843 /* Ignore standby in case of voip call because the voip output
1844 * stream is closed in adev_close_output_stream()
1845 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301846 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001847 return 0;
1848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001850 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 if (!out->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07001852 if (adev->adm_deregister_stream)
1853 adev->adm_deregister_stream(adev->adm_data, out->handle);
1854
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001855 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001857 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 if (out->pcm) {
1859 pcm_close(out->pcm);
1860 out->pcm = NULL;
1861 }
1862 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001863 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 stop_compressed_output_l(out);
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05301865 out->send_next_track_params = false;
1866 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 out->gapless_mdata.encoder_delay = 0;
1868 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001869 if (out->compr != NULL) {
1870 compress_close(out->compr);
1871 out->compr = NULL;
1872 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001875 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 }
1877 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001878 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 return 0;
1880}
1881
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001882static int out_dump(const struct audio_stream *stream __unused,
1883 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884{
1885 return 0;
1886}
1887
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001888static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1889{
1890 int ret = 0;
1891 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001892
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001893 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001894 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001895 return -EINVAL;
1896 }
1897
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301898 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001899
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001900 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1901 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301902 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001903 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001904 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1905 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301906 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001907 }
1908
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001909 ALOGV("%s new encoder delay %u and padding %u", __func__,
1910 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1911
1912 return 0;
1913}
1914
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001915static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1916{
1917 return out == adev->primary_output || out == adev->voice_tx_output;
1918}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1921{
1922 struct stream_out *out = (struct stream_out *)stream;
1923 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001924 struct audio_usecase *usecase;
1925 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 struct str_parms *parms;
1927 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001928 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001929 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
sangwoobc677242013-08-08 16:53:43 +09001931 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001932 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301934 if (!parms)
1935 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001936 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1937 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938 val = atoi(value);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07001939 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001940 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001942 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301943 * When HDMI cable is unplugged/usb hs is disconnected the
1944 * music playback is paused and the policy manager sends routing=0
1945 * But the audioflingercontinues to write data until standby time
1946 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 * Avoid this by routing audio to speaker until standby.
1948 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301949 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1950 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001951 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001952 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1953 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001954 }
1955
1956 /*
1957 * select_devices() call below switches all the usecases on the same
1958 * backend to the new device. Refer to check_usecases_codec_backend() in
1959 * the select_devices(). But how do we undo this?
1960 *
1961 * For example, music playback is active on headset (deep-buffer usecase)
1962 * and if we go to ringtones and select a ringtone, low-latency usecase
1963 * will be started on headset+speaker. As we can't enable headset+speaker
1964 * and headset devices at the same time, select_devices() switches the music
1965 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1966 * So when the ringtone playback is completed, how do we undo the same?
1967 *
1968 * We are relying on the out_set_parameters() call on deep-buffer output,
1969 * once the ringtone playback is ended.
1970 * NOTE: We should not check if the current devices are same as new devices.
1971 * Because select_devices() must be called to switch back the music
1972 * playback to headset.
1973 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001974 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001975 out->devices = val;
1976
1977 if (!out->standby)
1978 select_devices(adev, out->usecase);
1979
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001980 if (output_drives_call(adev, out)) {
1981 if(!voice_is_in_call(adev)) {
1982 if (adev->mode == AUDIO_MODE_IN_CALL) {
1983 adev->current_call_output = out;
1984 ret = voice_start_call(adev);
1985 }
1986 } else {
1987 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001988 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001989 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001990 }
1991 }
1992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001994 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001996
1997 if (out == adev->primary_output) {
1998 pthread_mutex_lock(&adev->lock);
1999 audio_extn_set_parameters(adev, parms);
2000 pthread_mutex_unlock(&adev->lock);
2001 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002002 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002003 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002004 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002005
2006 audio_extn_dts_create_state_notifier_node(out->usecase);
2007 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2008 popcount(out->channel_mask),
2009 out->playback_started);
2010
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002011 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002012 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302015error:
Eric Laurent994a6932013-07-17 11:51:42 -07002016 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 return ret;
2018}
2019
2020static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2021{
2022 struct stream_out *out = (struct stream_out *)stream;
2023 struct str_parms *query = str_parms_create_str(keys);
2024 char *str;
2025 char value[256];
2026 struct str_parms *reply = str_parms_create();
2027 size_t i, j;
2028 int ret;
2029 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002030
2031 if (!query || !reply) {
2032 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2033 return NULL;
2034 }
2035
Eric Laurent994a6932013-07-17 11:51:42 -07002036 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2038 if (ret >= 0) {
2039 value[0] = '\0';
2040 i = 0;
2041 while (out->supported_channel_masks[i] != 0) {
2042 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2043 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2044 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002045 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002047 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 first = false;
2049 break;
2050 }
2051 }
2052 i++;
2053 }
2054 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2055 str = str_parms_to_str(reply);
2056 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002057 voice_extn_out_get_parameters(out, query, reply);
2058 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002059 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002060 free(str);
2061 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002062 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002064
2065 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2066 if (ret >= 0) {
2067 value[0] = '\0';
2068 i = 0;
2069 first = true;
2070 while (out->supported_formats[i] != 0) {
2071 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2072 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2073 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002074 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002075 }
2076 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2077 first = false;
2078 break;
2079 }
2080 }
2081 i++;
2082 }
2083 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2084 str = str_parms_to_str(reply);
2085 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086 str_parms_destroy(query);
2087 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002088 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 return str;
2090}
2091
2092static uint32_t out_get_latency(const struct audio_stream_out *stream)
2093{
2094 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002095 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096
Alexy Josephaa54c872014-12-03 02:46:47 -08002097 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002098 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002099 } else {
2100 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002102 }
2103
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302104 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002105 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106}
2107
2108static int out_set_volume(struct audio_stream_out *stream, float left,
2109 float right)
2110{
Eric Laurenta9024de2013-04-04 09:19:12 -07002111 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 int volume[2];
2113
Eric Laurenta9024de2013-04-04 09:19:12 -07002114 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2115 /* only take left channel into account: the API is for stereo anyway */
2116 out->muted = (left == 0.0f);
2117 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002118 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002119 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2120 /*
2121 * Set mute or umute on HDMI passthrough stream.
2122 * Only take left channel into account.
2123 * Mute is 0 and unmute 1
2124 */
2125 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2126 } else {
2127 char mixer_ctl_name[128];
2128 struct audio_device *adev = out->dev;
2129 struct mixer_ctl *ctl;
2130 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002131 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002133 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2134 "Compress Playback %d Volume", pcm_device_id);
2135 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2136 if (!ctl) {
2137 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2138 __func__, mixer_ctl_name);
2139 return -EINVAL;
2140 }
2141 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2142 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2143 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2144 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002146 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148 return -ENOSYS;
2149}
2150
2151static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2152 size_t bytes)
2153{
2154 struct stream_out *out = (struct stream_out *)stream;
2155 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302156 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002157 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002159 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302160
Naresh Tanniru80659832014-06-04 18:17:56 +05302161 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002162 // increase written size during SSR to avoid mismatch
2163 // with the written frames count in AF
2164 if (!is_offload_usecase(out->usecase))
2165 out->written += bytes / (out->config.channels * sizeof(short));
2166
Naresh Tanniru80659832014-06-04 18:17:56 +05302167 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302168 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302169 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302170 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002171 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302172 //during SSR for compress usecase we should return error to flinger
2173 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2174 pthread_mutex_unlock(&out->lock);
2175 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302176 }
2177 }
2178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002180 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002181 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002182 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2183 ret = voice_extn_compress_voip_start_output_stream(out);
2184 else
2185 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002186 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002189 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 goto exit;
2191 }
Naresh Tanniru4a080142015-06-15 10:35:19 -07002192 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD && adev->adm_register_output_stream)
2193 adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302196 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2197 setChannelStatus(out, buffer, bytes);
2198 adev->mChannelStatusSet = true;
2199 }
2200
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002201 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002202 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002203 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002204 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002205 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2206 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05302207 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2208 ALOGD("copl(%p):send next track params in gapless", out);
2209 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2210 out->send_next_track_params = false;
2211 out->is_compr_metadata_avail = false;
2212 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002213 }
2214
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302216 if (ret < 0)
2217 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002218 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002219 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302220 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 } else if (-ENETRESET == ret) {
2223 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2224 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2225 pthread_mutex_unlock(&out->lock);
2226 out_standby(&out->stream.common);
2227 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002230 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002231 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 out->playback_started = 1;
2233 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002234
2235 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2236 popcount(out->channel_mask),
2237 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 }
2239 pthread_mutex_unlock(&out->lock);
2240 return ret;
2241 } else {
2242 if (out->pcm) {
2243 if (out->muted)
2244 memset((void *)buffer, 0, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002247
2248 if (adev->adm_request_focus)
2249 adev->adm_request_focus(adev->adm_data, out->handle);
2250
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002251 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2252 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2253 else
2254 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Naresh Tanniru4a080142015-06-15 10:35:19 -07002255
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302256 if (ret < 0)
2257 ret = -errno;
2258 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002259 out->written += bytes / (out->config.channels * sizeof(short));
Naresh Tanniru4a080142015-06-15 10:35:19 -07002260
2261 if (adev->adm_abandon_focus)
2262 adev->adm_abandon_focus(adev->adm_data, out->handle);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 }
2265
2266exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302267 /* ToDo: There may be a corner case when SSR happens back to back during
2268 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302269 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302270 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302271 }
2272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 pthread_mutex_unlock(&out->lock);
2274
2275 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002276 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002277 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302278 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302279 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302280 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302281 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302282 out->standby = true;
2283 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002285 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302286 out_get_sample_rate(&out->stream.common));
2287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288 }
2289 return bytes;
2290}
2291
2292static int out_get_render_position(const struct audio_stream_out *stream,
2293 uint32_t *dsp_frames)
2294{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002295 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302296 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002297
2298 if (dsp_frames == NULL)
2299 return -EINVAL;
2300
2301 *dsp_frames = 0;
2302 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002303 ssize_t ret = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002304 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002305 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302306 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002307 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302308 if (ret < 0)
2309 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 ALOGVV("%s rendered frames %d sample_rate %d",
2311 __func__, *dsp_frames, out->sample_rate);
2312 }
2313 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302314 if (-ENETRESET == ret) {
2315 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2316 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2317 return -EINVAL;
2318 } else if(ret < 0) {
2319 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2320 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302321 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2322 /*
2323 * Handle corner case where compress session is closed during SSR
2324 * and timestamp is queried
2325 */
2326 ALOGE(" ERROR: sound card not active, return error");
2327 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302328 } else {
2329 return 0;
2330 }
Zhou Song32a556e2015-05-05 10:46:56 +08002331 } else if (audio_is_linear_pcm(out->format)) {
2332 *dsp_frames = out->written;
2333 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002334 } else
2335 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336}
2337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002338static int out_add_audio_effect(const struct audio_stream *stream __unused,
2339 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340{
2341 return 0;
2342}
2343
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002344static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2345 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346{
2347 return 0;
2348}
2349
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002350static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2351 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352{
2353 return -EINVAL;
2354}
2355
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002356static int out_get_presentation_position(const struct audio_stream_out *stream,
2357 uint64_t *frames, struct timespec *timestamp)
2358{
2359 struct stream_out *out = (struct stream_out *)stream;
2360 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002361 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002362
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002363 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002364
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002365 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002366 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302367 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002368 &out->sample_rate);
2369 ALOGVV("%s rendered frames %ld sample_rate %d",
2370 __func__, dsp_frames, out->sample_rate);
2371 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302372 if (ret < 0)
2373 ret = -errno;
2374 if (-ENETRESET == ret) {
2375 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2376 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2377 ret = -EINVAL;
2378 } else
2379 ret = 0;
2380
Eric Laurent949a0892013-09-20 09:20:13 -07002381 /* this is the best we can do */
2382 clock_gettime(CLOCK_MONOTONIC, timestamp);
2383 }
2384 } else {
2385 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002386 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002387 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2388 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002389 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002390 // This adjustment accounts for buffering after app processor.
2391 // It is based on estimated DSP latency per use case, rather than exact.
2392 signed_frames -=
2393 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2394
Eric Laurent949a0892013-09-20 09:20:13 -07002395 // It would be unusual for this value to be negative, but check just in case ...
2396 if (signed_frames >= 0) {
2397 *frames = signed_frames;
2398 ret = 0;
2399 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002400 }
2401 }
2402 }
2403
2404 pthread_mutex_unlock(&out->lock);
2405
2406 return ret;
2407}
2408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409static int out_set_callback(struct audio_stream_out *stream,
2410 stream_callback_t callback, void *cookie)
2411{
2412 struct stream_out *out = (struct stream_out *)stream;
2413
2414 ALOGV("%s", __func__);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002415 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 out->offload_callback = callback;
2417 out->offload_cookie = cookie;
2418 pthread_mutex_unlock(&out->lock);
2419 return 0;
2420}
2421
2422static int out_pause(struct audio_stream_out* stream)
2423{
2424 struct stream_out *out = (struct stream_out *)stream;
2425 int status = -ENOSYS;
2426 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002427 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002428 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002429 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302431 struct audio_device *adev = out->dev;
2432 int snd_scard_state = get_snd_card_state(adev);
2433
2434 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2435 status = compress_pause(out->compr);
2436
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002438
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302439 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002440 audio_extn_dts_notify_playback_state(out->usecase, 0,
2441 out->sample_rate, popcount(out->channel_mask),
2442 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443 }
2444 pthread_mutex_unlock(&out->lock);
2445 }
2446 return status;
2447}
2448
2449static int out_resume(struct audio_stream_out* stream)
2450{
2451 struct stream_out *out = (struct stream_out *)stream;
2452 int status = -ENOSYS;
2453 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002454 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002455 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002456 status = 0;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002457 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002458 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302459 struct audio_device *adev = out->dev;
2460 int snd_scard_state = get_snd_card_state(adev);
2461
2462 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2463 status = compress_resume(out->compr);
2464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002465 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002466
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302467 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002468 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2469 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 }
2471 pthread_mutex_unlock(&out->lock);
2472 }
2473 return status;
2474}
2475
2476static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2477{
2478 struct stream_out *out = (struct stream_out *)stream;
2479 int status = -ENOSYS;
2480 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002481 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002482 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002483 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2484 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2485 else
2486 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2487 pthread_mutex_unlock(&out->lock);
2488 }
2489 return status;
2490}
2491
2492static int out_flush(struct audio_stream_out* stream)
2493{
2494 struct stream_out *out = (struct stream_out *)stream;
2495 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002496 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002497 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002498 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002499 stop_compressed_output_l(out);
2500 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002501 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 return 0;
2503 }
2504 return -ENOSYS;
2505}
2506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507/** audio_stream_in implementation **/
2508static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2509{
2510 struct stream_in *in = (struct stream_in *)stream;
2511
2512 return in->config.rate;
2513}
2514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002515static int in_set_sample_rate(struct audio_stream *stream __unused,
2516 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517{
2518 return -ENOSYS;
2519}
2520
2521static size_t in_get_buffer_size(const struct audio_stream *stream)
2522{
2523 struct stream_in *in = (struct stream_in *)stream;
2524
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002525 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2526 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002527 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2528 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002529
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002530 return in->config.period_size *
2531 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532}
2533
2534static uint32_t in_get_channels(const struct audio_stream *stream)
2535{
2536 struct stream_in *in = (struct stream_in *)stream;
2537
2538 return in->channel_mask;
2539}
2540
2541static audio_format_t in_get_format(const struct audio_stream *stream)
2542{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002543 struct stream_in *in = (struct stream_in *)stream;
2544
2545 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546}
2547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002548static int in_set_format(struct audio_stream *stream __unused,
2549 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550{
2551 return -ENOSYS;
2552}
2553
2554static int in_standby(struct audio_stream *stream)
2555{
2556 struct stream_in *in = (struct stream_in *)stream;
2557 struct audio_device *adev = in->dev;
2558 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302559 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2560 stream, in->usecase, use_case_table[in->usecase]);
2561
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002562 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2563 /* Ignore standby in case of voip call because the voip input
2564 * stream is closed in adev_close_input_stream()
2565 */
2566 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2567 return status;
2568 }
2569
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002570 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002571 if (!in->standby && in->is_st_session) {
2572 ALOGD("%s: sound trigger pcm stop lab", __func__);
2573 audio_extn_sound_trigger_stop_lab(in);
2574 in->standby = 1;
2575 }
2576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 if (!in->standby) {
Naresh Tanniru4a080142015-06-15 10:35:19 -07002578 if (adev->adm_deregister_stream)
2579 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2580
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002581 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002583 if (in->pcm) {
2584 pcm_close(in->pcm);
2585 in->pcm = NULL;
2586 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002588 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 }
2590 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002591 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 return status;
2593}
2594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002595static int in_dump(const struct audio_stream *stream __unused,
2596 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597{
2598 return 0;
2599}
2600
2601static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2602{
2603 struct stream_in *in = (struct stream_in *)stream;
2604 struct audio_device *adev = in->dev;
2605 struct str_parms *parms;
2606 char *str;
2607 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002608 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302610 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 parms = str_parms_create_str(kvpairs);
2612
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302613 if (!parms)
2614 goto error;
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002615 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002616 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002617
2618 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2619 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 val = atoi(value);
2621 /* no audio source uses val == 0 */
2622 if ((in->source != val) && (val != 0)) {
2623 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002624 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2625 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2626 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2627 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002628 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002629 err = voice_extn_compress_voip_open_input_stream(in);
2630 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002631 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002632 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002633 }
2634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 }
2636 }
2637
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002638 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2639 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002641 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 in->device = val;
2643 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002644 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002645 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 }
2647 }
2648
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002649done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002651 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652
2653 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302654error:
Eric Laurent994a6932013-07-17 11:51:42 -07002655 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 return ret;
2657}
2658
2659static char* in_get_parameters(const struct audio_stream *stream,
2660 const char *keys)
2661{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002662 struct stream_in *in = (struct stream_in *)stream;
2663 struct str_parms *query = str_parms_create_str(keys);
2664 char *str;
2665 char value[256];
2666 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002667
2668 if (!query || !reply) {
2669 ALOGE("in_get_parameters: failed to create query or reply");
2670 return NULL;
2671 }
2672
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002673 ALOGV("%s: enter: keys - %s", __func__, keys);
2674
2675 voice_extn_in_get_parameters(in, query, reply);
2676
2677 str = str_parms_to_str(reply);
2678 str_parms_destroy(query);
2679 str_parms_destroy(reply);
2680
2681 ALOGV("%s: exit: returns - %s", __func__, str);
2682 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683}
2684
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002685static int in_set_gain(struct audio_stream_in *stream __unused,
2686 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687{
2688 return 0;
2689}
2690
2691static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2692 size_t bytes)
2693{
2694 struct stream_in *in = (struct stream_in *)stream;
2695 struct audio_device *adev = in->dev;
2696 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302697 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002699 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302700
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002701 if (in->is_st_session) {
2702 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2703 /* Read from sound trigger HAL */
2704 audio_extn_sound_trigger_read(in, buffer, bytes);
2705 pthread_mutex_unlock(&in->lock);
2706 return bytes;
2707 }
2708
2709 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2710 ALOGD(" %s: sound card is not active/SSR state", __func__);
2711 ret= -EIO;;
2712 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302713 }
2714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002716 pthread_mutex_lock(&adev->lock);
2717 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2718 ret = voice_extn_compress_voip_start_input_stream(in);
2719 else
2720 ret = start_input_stream(in);
2721 pthread_mutex_unlock(&adev->lock);
2722 if (ret != 0) {
2723 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 }
2725 in->standby = 0;
Naresh Tanniru4a080142015-06-15 10:35:19 -07002726 if (adev->adm_register_input_stream)
2727 adev->adm_register_input_stream(adev->adm_data, in->capture_handle, in->flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729
Naresh Tanniru4a080142015-06-15 10:35:19 -07002730 if (adev->adm_request_focus)
2731 adev->adm_request_focus(adev->adm_data, in->capture_handle);
2732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002734 if (audio_extn_ssr_get_enabled() &&
2735 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002736 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002737 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2738 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002739 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2740 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002741 else
2742 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302743 if (ret < 0)
2744 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 }
2746
Naresh Tanniru4a080142015-06-15 10:35:19 -07002747 if (adev->adm_abandon_focus)
2748 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
2749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 /*
2751 * Instead of writing zeroes here, we could trust the hardware
2752 * to always provide zeroes when muted.
2753 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302754 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2755 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 memset(buffer, 0, bytes);
2757
2758exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302759 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302760 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002761 if (-ENETRESET == ret)
2762 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 pthread_mutex_unlock(&in->lock);
2765
2766 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302767 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302768 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302769 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302770 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302771 in->standby = true;
2772 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302773 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002775 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002776 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302777 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 }
2779 return bytes;
2780}
2781
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002782static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783{
2784 return 0;
2785}
2786
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002787static int add_remove_audio_effect(const struct audio_stream *stream,
2788 effect_handle_t effect,
2789 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002791 struct stream_in *in = (struct stream_in *)stream;
2792 int status = 0;
2793 effect_descriptor_t desc;
2794
2795 status = (*effect)->get_descriptor(effect, &desc);
2796 if (status != 0)
2797 return status;
2798
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002799 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002800 pthread_mutex_lock(&in->dev->lock);
2801 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2802 in->enable_aec != enable &&
2803 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2804 in->enable_aec = enable;
2805 if (!in->standby)
2806 select_devices(in->dev, in->usecase);
2807 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002808 if (in->enable_ns != enable &&
2809 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2810 in->enable_ns = enable;
2811 if (!in->standby)
2812 select_devices(in->dev, in->usecase);
2813 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002814 pthread_mutex_unlock(&in->dev->lock);
2815 pthread_mutex_unlock(&in->lock);
2816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 return 0;
2818}
2819
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002820static int in_add_audio_effect(const struct audio_stream *stream,
2821 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822{
Eric Laurent994a6932013-07-17 11:51:42 -07002823 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002824 return add_remove_audio_effect(stream, effect, true);
2825}
2826
2827static int in_remove_audio_effect(const struct audio_stream *stream,
2828 effect_handle_t effect)
2829{
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002831 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832}
2833
2834static int adev_open_output_stream(struct audio_hw_device *dev,
2835 audio_io_handle_t handle,
2836 audio_devices_t devices,
2837 audio_output_flags_t flags,
2838 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002839 struct audio_stream_out **stream_out,
2840 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841{
2842 struct audio_device *adev = (struct audio_device *)dev;
2843 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002844 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002845 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302848
2849 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2850 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
Naresh Tanniru06f99432015-08-26 14:01:20 -07002851 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05302852 return -EINVAL;
2853 }
2854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2856
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302857 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2858 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2859 devices, flags, &out->stream);
2860
2861
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002862 if (!out) {
2863 return -ENOMEM;
2864 }
2865
Haynes Mathew George204045b2015-02-25 20:32:03 -08002866 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07002867 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08002868 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 if (devices == AUDIO_DEVICE_NONE)
2871 devices = AUDIO_DEVICE_OUT_SPEAKER;
2872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 out->flags = flags;
2874 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002875 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002876 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->sample_rate = config->sample_rate;
2878 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2879 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002880 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002881 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002882 out->non_blocking = 0;
2883 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302885 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2886 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002887 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2888 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2889
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002890 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002891 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2892 ret = read_hdmi_channel_masks(out);
2893
2894 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2895 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002896 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002897 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002898 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002899
2900 if (config->sample_rate == 0)
2901 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2902 if (config->channel_mask == 0)
2903 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2904
2905 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2908 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002910 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002912 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2913 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002914 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002915 ret = voice_extn_compress_voip_open_output_stream(out);
2916 if (ret != 0) {
2917 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2918 __func__, ret);
2919 goto error_open;
2920 }
Naresh Tanniru06f99432015-08-26 14:01:20 -07002921 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2922 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2925 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2926 ALOGE("%s: Unsupported Offload information", __func__);
2927 ret = -EINVAL;
2928 goto error_open;
2929 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002930
2931 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2932 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2933 ALOGV("read and update_pass through formats");
2934 ret = audio_extn_dolby_update_passt_formats(adev, out);
2935 if(ret != 0) {
2936 goto error_open;
2937 }
2938 if(config->offload_info.format == 0)
2939 config->offload_info.format = out->supported_formats[0];
2940 }
2941
Mingming Yin90310102013-11-13 16:57:00 -08002942 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002943 !audio_extn_is_dolby_format(config->offload_info.format)) {
Naresh Tanniru06f99432015-08-26 14:01:20 -07002944 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 ret = -EINVAL;
2946 goto error_open;
2947 }
2948
2949 out->compr_config.codec = (struct snd_codec *)
2950 calloc(1, sizeof(struct snd_codec));
2951
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002952 if (!out->compr_config.codec) {
2953 ret = -ENOMEM;
2954 goto error_open;
2955 }
2956
Naresh Tanniru06f99432015-08-26 14:01:20 -07002957 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2958 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2959 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2960 } else {
2961 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2962 out->usecase = get_offload_usecase(adev);
Mingming Yin882890f2015-09-30 13:56:25 -07002963
2964 out->stream.set_callback = out_set_callback;
2965 out->stream.pause = out_pause;
2966 out->stream.resume = out_resume;
2967 out->stream.drain = out_drain;
2968 out->stream.flush = out_flush;
Naresh Tanniru06f99432015-08-26 14:01:20 -07002969 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002970 if (config->offload_info.channel_mask)
2971 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002972 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002974 config->offload_info.channel_mask = config->channel_mask;
2975 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002976 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 out->sample_rate = config->offload_info.sample_rate;
2978
Mingming Yin3ee55c62014-08-04 14:23:35 -07002979 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002981 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002982 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002983 audio_extn_dolby_get_snd_codec_id(adev, out,
2984 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002985 else
2986 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002987 get_snd_codec_id(config->offload_info.format);
Naresh Tanniru06f99432015-08-26 14:01:20 -07002988
2989 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2990 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002991 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002992 platform_get_pcm_offload_buffer_size(&config->offload_info);
2993 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2994 out->compr_config.fragment_size =
2995 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002996 } else {
2997 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002998 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002999 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3001 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08003002 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 out->compr_config.codec->bit_rate =
3004 config->offload_info.bit_rate;
3005 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003006 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05303008 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003009 /*TODO: Do we need to change it for passthrough */
3010 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011
Manish Dewangan93672f12015-08-24 20:30:31 +05303012 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3013 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3014 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3015 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003016 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
3017 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Naresh Tanniru06f99432015-08-26 14:01:20 -07003018 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003019 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
Naresh Tanniru06f99432015-08-26 14:01:20 -07003020 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
3021 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003022
Mingming Yin3ee55c62014-08-04 14:23:35 -07003023 if (out->bit_width == 24) {
3024 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
3025 }
3026
Amit Shekhar6f461b12014-08-01 14:52:58 -07003027 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05303028 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3031 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003032
Sharad Sangleb27354b2015-06-18 15:58:55 +05303033 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08003034 //this flag is set from framework only if its for PCM formats
3035 //no need to check for PCM format again
3036 out->non_blocking = 0;
3037 out->use_small_bufs = true;
3038 ALOGI("Keep write blocking for small buff: non_blockling %d",
3039 out->non_blocking);
3040 }
3041
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003042 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajubc739cb2015-07-24 14:15:05 +05303043 out->send_next_track_params = false;
3044 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003045 out->offload_state = OFFLOAD_STATE_IDLE;
3046 out->playback_started = 0;
3047
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003048 audio_extn_dts_create_state_notifier_node(out->usecase);
3049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 create_offload_callback_thread(out);
3051 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3052 __func__, config->offload_info.version,
3053 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08003054 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08003055 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003056 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3057 ret = voice_check_and_set_incall_music_usecase(adev, out);
3058 if (ret != 0) {
3059 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3060 __func__, ret);
3061 goto error_open;
3062 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003063 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3064 if (config->sample_rate == 0)
3065 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3066 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3067 config->sample_rate != 8000) {
3068 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3069 ret = -EINVAL;
3070 goto error_open;
3071 }
3072 out->sample_rate = config->sample_rate;
3073 out->config.rate = config->sample_rate;
3074 if (config->format == AUDIO_FORMAT_DEFAULT)
3075 config->format = AUDIO_FORMAT_PCM_16_BIT;
3076 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3077 config->format = AUDIO_FORMAT_PCM_16_BIT;
3078 ret = -EINVAL;
3079 goto error_open;
3080 }
3081 out->format = config->format;
3082 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3083 out->config = pcm_config_afe_proxy_playback;
3084 adev->voice_tx_output = out;
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003085 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3086 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3087 out->config = pcm_config_low_latency;
3088 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003089 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003090 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3092 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003094 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3095 format = AUDIO_FORMAT_PCM_16_BIT;
3096 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3097 out->config = pcm_config_deep_buffer;
3098 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003099 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003100 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003101 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003102 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003103 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003104 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 }
3106
Amit Shekhar1d896042014-10-03 13:16:09 -07003107 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3108 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003109 /* TODO remove this hardcoding and check why width is zero*/
3110 if (out->bit_width == 0)
3111 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003112 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3113 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003114 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303115 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003116 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3117 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3118 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003119 if(adev->primary_output == NULL)
3120 adev->primary_output = out;
3121 else {
3122 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003123 ret = -EEXIST;
3124 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003125 }
3126 }
3127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 /* Check if this usecase is already existing */
3129 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003130 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3131 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003134 ret = -EEXIST;
3135 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 }
3137 pthread_mutex_unlock(&adev->lock);
3138
3139 out->stream.common.get_sample_rate = out_get_sample_rate;
3140 out->stream.common.set_sample_rate = out_set_sample_rate;
3141 out->stream.common.get_buffer_size = out_get_buffer_size;
3142 out->stream.common.get_channels = out_get_channels;
3143 out->stream.common.get_format = out_get_format;
3144 out->stream.common.set_format = out_set_format;
3145 out->stream.common.standby = out_standby;
3146 out->stream.common.dump = out_dump;
3147 out->stream.common.set_parameters = out_set_parameters;
3148 out->stream.common.get_parameters = out_get_parameters;
3149 out->stream.common.add_audio_effect = out_add_audio_effect;
3150 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3151 out->stream.get_latency = out_get_latency;
3152 out->stream.set_volume = out_set_volume;
3153 out->stream.write = out_write;
3154 out->stream.get_render_position = out_get_render_position;
3155 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003156 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003159 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003160 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161
3162 config->format = out->stream.common.get_format(&out->stream.common);
3163 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3164 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3165
3166 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303167 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
Naresh Tanniru06f99432015-08-26 14:01:20 -07003168 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003169
3170 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3171 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3172 popcount(out->channel_mask), out->playback_started);
3173
Eric Laurent994a6932013-07-17 11:51:42 -07003174 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003176
3177error_open:
3178 free(out);
3179 *stream_out = NULL;
3180 ALOGD("%s: exit: ret %d", __func__, ret);
3181 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182}
3183
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003184static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 struct audio_stream_out *stream)
3186{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 struct stream_out *out = (struct stream_out *)stream;
3188 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003189 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303191 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3192
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003193 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303194 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003195 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303196 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003197 if(ret != 0)
3198 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3199 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003200 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003201 out_standby(&stream->common);
3202
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003203 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003204 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003206 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003207 if (out->compr_config.codec != NULL)
3208 free(out->compr_config.codec);
3209 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003210
3211 if (adev->voice_tx_output == out)
3212 adev->voice_tx_output = NULL;
3213
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 pthread_cond_destroy(&out->cond);
3215 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003217 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218}
3219
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003220static void close_compress_sessions(struct audio_device *adev)
3221{
Mingming Yin7b762e72015-03-04 13:47:32 -08003222 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303223 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003224 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003225 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303226
3227 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003228 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303229 if (is_offload_usecase(usecase->id)) {
3230 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003231 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3232 out = usecase->stream.out;
3233 pthread_mutex_unlock(&adev->lock);
3234 out_standby(&out->stream.common);
3235 pthread_mutex_lock(&adev->lock);
3236 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303237 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003238 }
3239 pthread_mutex_unlock(&adev->lock);
3240}
3241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3243{
3244 struct audio_device *adev = (struct audio_device *)dev;
3245 struct str_parms *parms;
3246 char *str;
3247 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003248 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003249 int ret;
3250 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003252 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303255 if (!parms)
3256 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003257 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3258 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303259 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303260 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303261 struct listnode *node;
3262 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303263 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303264 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003265 //close compress sessions on OFFLINE status
3266 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303267 } else if (strstr(snd_card_status, "ONLINE")) {
3268 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303269 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303270 if (!platform_is_acdb_initialized(adev->platform)) {
3271 ret = platform_acdb_init(adev->platform);
3272 if(ret)
3273 ALOGE("acdb initialization is failed");
3274
3275 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303276 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303277 }
3278
3279 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003280 status = voice_set_parameters(adev, parms);
3281 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003282 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003284 status = platform_set_parameters(adev->platform, parms);
3285 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003286 goto done;
3287
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003288 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3289 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003290 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3292 adev->bluetooth_nrec = true;
3293 else
3294 adev->bluetooth_nrec = false;
3295 }
3296
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003297 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3298 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3300 adev->screen_off = false;
3301 else
3302 adev->screen_off = true;
3303 }
3304
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003305 ret = str_parms_get_int(parms, "rotation", &val);
3306 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003307 bool reverse_speakers = false;
3308 switch(val) {
3309 // FIXME: note that the code below assumes that the speakers are in the correct placement
3310 // relative to the user when the device is rotated 90deg from its default rotation. This
3311 // assumption is device-specific, not platform-specific like this code.
3312 case 270:
3313 reverse_speakers = true;
3314 break;
3315 case 0:
3316 case 90:
3317 case 180:
3318 break;
3319 default:
3320 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003321 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003322 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003323 if (status == 0) {
3324 if (adev->speaker_lr_swap != reverse_speakers) {
3325 adev->speaker_lr_swap = reverse_speakers;
3326 // only update the selected device if there is active pcm playback
3327 struct audio_usecase *usecase;
3328 struct listnode *node;
3329 list_for_each(node, &adev->usecase_list) {
3330 usecase = node_to_item(node, struct audio_usecase, list);
3331 if (usecase->type == PCM_PLAYBACK) {
3332 select_devices(adev, usecase->id);
3333 break;
3334 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003335 }
3336 }
3337 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003338 }
3339
Mingming Yin514a8bc2014-07-29 15:22:21 -07003340 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3341 if (ret >= 0) {
3342 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3343 adev->bt_wb_speech_enabled = true;
3344 else
3345 adev->bt_wb_speech_enabled = false;
3346 }
3347
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003348 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3349 if (ret >= 0) {
3350 val = atoi(value);
3351 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3352 ALOGV("cache new edid");
3353 platform_cache_edid(adev->platform);
3354 }
3355 }
3356
3357 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3358 if (ret >= 0) {
3359 val = atoi(value);
3360 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3361 ALOGV("invalidate cached edid");
3362 platform_invalidate_edid(adev->platform);
3363 }
3364 }
3365
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003366 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003367
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003368done:
3369 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003370 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303371error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003372 ALOGV("%s: exit with code(%d)", __func__, status);
3373 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374}
3375
3376static char* adev_get_parameters(const struct audio_hw_device *dev,
3377 const char *keys)
3378{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003379 struct audio_device *adev = (struct audio_device *)dev;
3380 struct str_parms *reply = str_parms_create();
3381 struct str_parms *query = str_parms_create_str(keys);
3382 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303383 char value[256] = {0};
3384 int ret = 0;
3385
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003386 if (!query || !reply) {
3387 ALOGE("adev_get_parameters: failed to create query or reply");
3388 return NULL;
3389 }
3390
Naresh Tannirud7205b62014-06-20 02:54:48 +05303391 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3392 sizeof(value));
3393 if (ret >=0) {
3394 int val = 1;
3395 pthread_mutex_lock(&adev->snd_card_status.lock);
3396 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3397 val = 0;
3398 pthread_mutex_unlock(&adev->snd_card_status.lock);
3399 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3400 goto exit;
3401 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003402
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003403 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003404 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003405 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003406 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303407 pthread_mutex_unlock(&adev->lock);
3408
Naresh Tannirud7205b62014-06-20 02:54:48 +05303409exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003410 str = str_parms_to_str(reply);
3411 str_parms_destroy(query);
3412 str_parms_destroy(reply);
3413
3414 ALOGV("%s: exit: returns - %s", __func__, str);
3415 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416}
3417
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003418static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419{
3420 return 0;
3421}
3422
3423static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3424{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003425 int ret;
3426 struct audio_device *adev = (struct audio_device *)dev;
3427 pthread_mutex_lock(&adev->lock);
3428 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003429 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003430 pthread_mutex_unlock(&adev->lock);
3431 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432}
3433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003434static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3435 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436{
3437 return -ENOSYS;
3438}
3439
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003440static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3441 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442{
3443 return -ENOSYS;
3444}
3445
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003446static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3447 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448{
3449 return -ENOSYS;
3450}
3451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003452static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3453 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454{
3455 return -ENOSYS;
3456}
3457
3458static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3459{
3460 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 pthread_mutex_lock(&adev->lock);
3463 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003464 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003466 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3467 voice_is_in_call(adev)) {
3468 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303469 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003470 adev->current_call_output = NULL;
3471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 }
3473 pthread_mutex_unlock(&adev->lock);
3474 return 0;
3475}
3476
3477static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3478{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003479 int ret;
3480
3481 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003482 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003483 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3484 pthread_mutex_unlock(&adev->lock);
3485
3486 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487}
3488
3489static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3490{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003491 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 return 0;
3493}
3494
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003495static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496 const struct audio_config *config)
3497{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003498 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003500 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3501 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502}
3503
3504static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003505 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 audio_devices_t devices,
3507 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003508 struct audio_stream_in **stream_in,
3509 audio_input_flags_t flags __unused,
3510 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003511 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512{
3513 struct audio_device *adev = (struct audio_device *)dev;
3514 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003515 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003516 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003517 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519 *stream_in = NULL;
3520 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3521 return -EINVAL;
3522
3523 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003524
3525 if (!in) {
3526 ALOGE("failed to allocate input stream");
3527 return -ENOMEM;
3528 }
3529
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303530 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003531 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3532 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003534 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahallid53b6692015-09-28 15:23:06 -07003535 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537 in->stream.common.get_sample_rate = in_get_sample_rate;
3538 in->stream.common.set_sample_rate = in_set_sample_rate;
3539 in->stream.common.get_buffer_size = in_get_buffer_size;
3540 in->stream.common.get_channels = in_get_channels;
3541 in->stream.common.get_format = in_get_format;
3542 in->stream.common.set_format = in_set_format;
3543 in->stream.common.standby = in_standby;
3544 in->stream.common.dump = in_dump;
3545 in->stream.common.set_parameters = in_set_parameters;
3546 in->stream.common.get_parameters = in_get_parameters;
3547 in->stream.common.add_audio_effect = in_add_audio_effect;
3548 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3549 in->stream.set_gain = in_set_gain;
3550 in->stream.read = in_read;
3551 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3552
3553 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003554 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 in->standby = 1;
3557 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003558 in->capture_handle = handle;
Naresh Tanniru4a080142015-06-15 10:35:19 -07003559 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
3561 /* Update config params with the requested sample rate and channels */
3562 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003563 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3564 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3565 is_low_latency = true;
3566#if LOW_LATENCY_CAPTURE_USE_CASE
3567 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3568#endif
3569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003572 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003574 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303575 if (adev->mode != AUDIO_MODE_IN_CALL) {
3576 ret = -EINVAL;
3577 goto err_open;
3578 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003579 if (config->sample_rate == 0)
3580 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3581 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3582 config->sample_rate != 8000) {
3583 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3584 ret = -EINVAL;
3585 goto err_open;
3586 }
3587 if (config->format == AUDIO_FORMAT_DEFAULT)
3588 config->format = AUDIO_FORMAT_PCM_16_BIT;
3589 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3590 config->format = AUDIO_FORMAT_PCM_16_BIT;
3591 ret = -EINVAL;
3592 goto err_open;
3593 }
3594
3595 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3596 in->config = pcm_config_afe_proxy_record;
3597 in->config.channels = channel_count;
3598 in->config.rate = config->sample_rate;
3599 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003600 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003601 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003602 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3603 ret = -EINVAL;
3604 goto err_open;
3605 }
3606 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003607 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003608 }
Mingming Yine62d7842013-10-25 16:26:03 -07003609 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003610 audio_extn_compr_cap_format_supported(config->format) &&
3611 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003612 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003613 } else {
3614 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003615 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003616 buffer_size = get_input_buffer_size(config->sample_rate,
3617 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003618 channel_count,
3619 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003620 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003621 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3622 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3623 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3624 (in->config.rate == 8000 || in->config.rate == 16000) &&
3625 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3626 voice_extn_compress_voip_open_input_stream(in);
3627 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003628 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003630 /* This stream could be for sound trigger lab,
3631 get sound trigger pcm if present */
3632 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303633 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003636 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003637 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638
3639err_open:
3640 free(in);
3641 *stream_in = NULL;
3642 return ret;
3643}
3644
3645static void adev_close_input_stream(struct audio_hw_device *dev,
3646 struct audio_stream_in *stream)
3647{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003648 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003649 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003650 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303651
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303652 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003653
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303654 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi95333352015-07-06 15:07:14 -07003655 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303656
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003657 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303658 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003659 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303660 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003661 if (ret != 0)
3662 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3663 __func__, ret);
3664 } else
3665 in_standby(&stream->common);
3666
Mingming Yin7b762e72015-03-04 13:47:32 -08003667 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003668 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003669 audio_extn_ssr_deinit();
3670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671
Mingming Yine62d7842013-10-25 16:26:03 -07003672 if(audio_extn_compr_cap_enabled() &&
3673 audio_extn_compr_cap_format_supported(in->config.format))
3674 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003675
3676 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 return;
3678}
3679
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003680static int adev_dump(const audio_hw_device_t *device __unused,
3681 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682{
3683 return 0;
3684}
3685
3686static int adev_close(hw_device_t *device)
3687{
3688 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003689
3690 if (!adev)
3691 return 0;
3692
3693 pthread_mutex_lock(&adev_init_lock);
3694
3695 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003696 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003697 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003698 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003699 audio_route_free(adev->audio_route);
3700 free(adev->snd_dev_ref_cnt);
3701 platform_deinit(adev->platform);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003702 if (adev->adm_deinit)
3703 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07003704 free(device);
3705 adev = NULL;
3706 }
3707 pthread_mutex_unlock(&adev_init_lock);
Naresh Tanniru4a080142015-06-15 10:35:19 -07003708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 return 0;
3710}
3711
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003712/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3713 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3714 * just that it _might_ work.
3715 */
3716static int period_size_is_plausible_for_low_latency(int period_size)
3717{
3718 switch (period_size) {
3719 case 160:
Naresh Tanniru3a7dbe72015-06-25 20:08:01 -07003720 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003721 case 240:
3722 case 320:
3723 case 480:
3724 return 1;
3725 default:
3726 return 0;
3727 }
3728}
3729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730static int adev_open(const hw_module_t *module, const char *name,
3731 hw_device_t **device)
3732{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003733 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003735 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3737
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003738 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003739 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003740 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003741 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003742 ALOGD("%s: returning existing instance of adev", __func__);
3743 ALOGD("%s: exit", __func__);
3744 pthread_mutex_unlock(&adev_init_lock);
3745 return 0;
3746 }
3747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 adev = calloc(1, sizeof(struct audio_device));
3749
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003750 if (!adev) {
3751 pthread_mutex_unlock(&adev_init_lock);
3752 return -ENOMEM;
3753 }
3754
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003755 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3758 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3759 adev->device.common.module = (struct hw_module_t *)module;
3760 adev->device.common.close = adev_close;
3761
3762 adev->device.init_check = adev_init_check;
3763 adev->device.set_voice_volume = adev_set_voice_volume;
3764 adev->device.set_master_volume = adev_set_master_volume;
3765 adev->device.get_master_volume = adev_get_master_volume;
3766 adev->device.set_master_mute = adev_set_master_mute;
3767 adev->device.get_master_mute = adev_get_master_mute;
3768 adev->device.set_mode = adev_set_mode;
3769 adev->device.set_mic_mute = adev_set_mic_mute;
3770 adev->device.get_mic_mute = adev_get_mic_mute;
3771 adev->device.set_parameters = adev_set_parameters;
3772 adev->device.get_parameters = adev_get_parameters;
3773 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3774 adev->device.open_output_stream = adev_open_output_stream;
3775 adev->device.close_output_stream = adev_close_output_stream;
3776 adev->device.open_input_stream = adev_open_input_stream;
3777 adev->device.close_input_stream = adev_close_input_stream;
3778 adev->device.dump = adev_dump;
3779
3780 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003782 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003783 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003786 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003787 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003788 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003789 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003790 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003791 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003792 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303793 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303794
3795 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3796 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003798 adev->platform = platform_init(adev);
3799 if (!adev->platform) {
3800 free(adev->snd_dev_ref_cnt);
3801 free(adev);
3802 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3803 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003804 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003805 return -EINVAL;
3806 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003807
Naresh Tanniru4c630392014-05-12 01:05:52 +05303808 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3809
Eric Laurentc4aef752013-09-12 17:45:53 -07003810 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3811 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3812 if (adev->visualizer_lib == NULL) {
3813 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3814 } else {
3815 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3816 adev->visualizer_start_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_start_output");
3819 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003820 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003821 "visualizer_hal_stop_output");
3822 }
3823 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003824 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003825 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003826
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003827 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3828 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3829 if (adev->offload_effects_lib == NULL) {
3830 ALOGE("%s: DLOPEN failed for %s", __func__,
3831 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3832 } else {
3833 ALOGV("%s: DLOPEN successful for %s", __func__,
3834 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3835 adev->offload_effects_start_output =
3836 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3837 "offload_effects_bundle_hal_start_output");
3838 adev->offload_effects_stop_output =
3839 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3840 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003841 adev->offload_effects_set_hpx_state =
3842 (int (*)(bool))dlsym(adev->offload_effects_lib,
3843 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumarc60410e2015-09-04 13:39:26 +05303844 adev->offload_effects_get_parameters =
3845 (void (*)(struct str_parms *, struct str_parms *))
3846 dlsym(adev->offload_effects_lib,
3847 "offload_effects_bundle_get_parameters");
3848 adev->offload_effects_set_parameters =
3849 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
3850 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003851 }
3852 }
3853
Naresh Tanniru4a080142015-06-15 10:35:19 -07003854 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
3855 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3856 if (adev->adm_lib == NULL) {
3857 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3858 } else {
3859 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3860 adev->adm_init = (adm_init_t)
3861 dlsym(adev->adm_lib, "adm_init");
3862 adev->adm_deinit = (adm_deinit_t)
3863 dlsym(adev->adm_lib, "adm_deinit");
3864 adev->adm_register_input_stream = (adm_register_input_stream_t)
3865 dlsym(adev->adm_lib, "adm_register_input_stream");
3866 adev->adm_register_output_stream = (adm_register_output_stream_t)
3867 dlsym(adev->adm_lib, "adm_register_output_stream");
3868 adev->adm_deregister_stream = (adm_deregister_stream_t)
3869 dlsym(adev->adm_lib, "adm_deregister_stream");
3870 adev->adm_request_focus = (adm_request_focus_t)
3871 dlsym(adev->adm_lib, "adm_request_focus");
3872 adev->adm_abandon_focus = (adm_abandon_focus_t)
3873 dlsym(adev->adm_lib, "adm_abandon_focus");
3874 }
3875 }
3876
Mingming Yin514a8bc2014-07-29 15:22:21 -07003877 adev->bt_wb_speech_enabled = false;
3878
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003879 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880 *device = &adev->device.common;
3881
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003882 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3883 &adev->streams_output_cfg_list);
3884
Kiran Kandi910e1862013-10-29 13:29:42 -07003885 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003886
3887 char value[PROPERTY_VALUE_MAX];
3888 int trial;
3889 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3890 trial = atoi(value);
3891 if (period_size_is_plausible_for_low_latency(trial)) {
3892 pcm_config_low_latency.period_size = trial;
3893 pcm_config_low_latency.start_threshold = trial / 4;
3894 pcm_config_low_latency.avail_min = trial / 4;
3895 configured_low_latency_capture_period_size = trial;
3896 }
3897 }
3898 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3899 trial = atoi(value);
3900 if (period_size_is_plausible_for_low_latency(trial)) {
3901 configured_low_latency_capture_period_size = trial;
3902 }
3903 }
3904
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003905 pthread_mutex_unlock(&adev_init_lock);
3906
Naresh Tanniru4a080142015-06-15 10:35:19 -07003907 if (adev->adm_init)
3908 adev->adm_data = adev->adm_init();
3909
Eric Laurent994a6932013-07-17 11:51:42 -07003910 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911 return 0;
3912}
3913
3914static struct hw_module_methods_t hal_module_methods = {
3915 .open = adev_open,
3916};
3917
3918struct audio_module HAL_MODULE_INFO_SYM = {
3919 .common = {
3920 .tag = HARDWARE_MODULE_TAG,
3921 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3922 .hal_api_version = HARDWARE_HAL_API_VERSION,
3923 .id = AUDIO_HARDWARE_MODULE_ID,
3924 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003925 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 .methods = &hal_module_methods,
3927 },
3928};