blob: da0f12d01acbc82eac9314ccb0f6e9ccae8dfdfe [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
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700446 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800489 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
490 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700492 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
493 adev->snd_dev_ref_cnt[snd_device]--;
494 return -EINVAL;
495 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200496 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 if (audio_extn_spkr_prot_start_processing(snd_device)) {
498 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200499 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800500 return -EINVAL;
501 }
502 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 ALOGV("%s: snd_device(%d: %s)", __func__,
504 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700505 /* due to the possibility of calibration overwrite between listen
506 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700507 audio_extn_sound_trigger_update_device_status(snd_device,
508 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530509 audio_extn_listen_update_device_status(snd_device,
510 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700511 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700513 audio_extn_sound_trigger_update_device_status(snd_device,
514 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530515 audio_extn_listen_update_device_status(snd_device,
516 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700517 return -EINVAL;
518 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300519 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 return 0;
523}
524
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700526 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
529
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800530 if (snd_device < SND_DEVICE_MIN ||
531 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800532 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800533 return -EINVAL;
534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
536 ALOGE("%s: device ref cnt is already 0", __func__);
537 return -EINVAL;
538 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700548 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800550 /* exit usb play back thread */
551 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
552 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
553 audio_extn_usb_stop_playback();
554
555 /* exit usb capture thread */
556 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700557 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700562 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300563 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700564 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200567 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568 audio_extn_sound_trigger_update_device_status(snd_device,
569 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530570 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800571 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 return 0;
575}
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577static void check_usecases_codec_backend(struct audio_device *adev,
578 struct audio_usecase *uc_info,
579 snd_device_t snd_device)
580{
581 struct listnode *node;
582 struct audio_usecase *usecase;
583 bool switch_device[AUDIO_USECASE_MAX];
584 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530585 int backend_idx = DEFAULT_CODEC_BACKEND;
586 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587
588 /*
589 * This function is to make sure that all the usecases that are active on
590 * the hardware codec backend are always routed to any one device that is
591 * handled by the hardware codec.
592 * For example, if low-latency and deep-buffer usecases are currently active
593 * on speaker and out_set_parameters(headset) is received on low-latency
594 * output, then we have to make sure deep-buffer is also switched to headset,
595 * because of the limitation that both the devices cannot be enabled
596 * at the same time as they share the same backend.
597 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700598 /*
599 * This call is to check if we need to force routing for a particular stream
600 * If there is a backend configuration change for the device when a
601 * new stream starts, then ADM needs to be closed and re-opened with the new
602 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530603 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700604 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530605 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
606 snd_device);
607 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800609 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800610 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 for (i = 0; i < AUDIO_USECASE_MAX; i++)
612 switch_device[i] = false;
613
614 list_for_each(node, &adev->usecase_list) {
615 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530616
617 if (usecase == uc_info)
618 continue;
619 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
620 ALOGV("%s: backend_idx: %d,"
621 "usecase_backend_idx: %d, curr device: %s, usecase device:"
622 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530623 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530624
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800625 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700626 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530627 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
628 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530629 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530630 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700631 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700632 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 switch_device[usecase->id] = true;
634 num_uc_to_switch++;
635 }
636 }
637
638 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700639 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530641 /* Make sure the previous devices to be disabled first and then enable the
642 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 list_for_each(node, &adev->usecase_list) {
644 usecase = node_to_item(node, struct audio_usecase, list);
645 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700646 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 }
648 }
649
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700650 list_for_each(node, &adev->usecase_list) {
651 usecase = node_to_item(node, struct audio_usecase, list);
652 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700653 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700654 }
655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 /* Re-route all the usecases on the shared backend other than the
658 specified usecase to new snd devices */
659 list_for_each(node, &adev->usecase_list) {
660 usecase = node_to_item(node, struct audio_usecase, list);
661 /* Update the out_snd_device only before enabling the audio route */
662 if (switch_device[usecase->id] ) {
663 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800664 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530665 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 }
667 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 }
669}
670
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700671static void check_and_route_capture_usecases(struct audio_device *adev,
672 struct audio_usecase *uc_info,
673 snd_device_t snd_device)
674{
675 struct listnode *node;
676 struct audio_usecase *usecase;
677 bool switch_device[AUDIO_USECASE_MAX];
678 int i, num_uc_to_switch = 0;
679
680 /*
681 * This function is to make sure that all the active capture usecases
682 * are always routed to the same input sound device.
683 * For example, if audio-record and voice-call usecases are currently
684 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
685 * is received for voice call then we have to make sure that audio-record
686 * usecase is also switched to earpiece i.e. voice-dmic-ef,
687 * because of the limitation that two devices cannot be enabled
688 * at the same time if they share the same backend.
689 */
690 for (i = 0; i < AUDIO_USECASE_MAX; i++)
691 switch_device[i] = false;
692
693 list_for_each(node, &adev->usecase_list) {
694 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800695 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700696 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700697 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530698 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700699 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700700 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
701 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700702 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700703 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 switch_device[usecase->id] = true;
705 num_uc_to_switch++;
706 }
707 }
708
709 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700710 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530712 /* Make sure the previous devices to be disabled first and then enable the
713 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714 list_for_each(node, &adev->usecase_list) {
715 usecase = node_to_item(node, struct audio_usecase, list);
716 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700717 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800718 }
719 }
720
721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
723 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700724 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700725 }
726 }
727
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728 /* Re-route all the usecases on the shared backend other than the
729 specified usecase to new snd devices */
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 /* Update the in_snd_device only before enabling the audio route */
733 if (switch_device[usecase->id] ) {
734 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800735 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530736 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 }
738 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 }
740}
741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800742/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700743static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700745 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700746 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747
748 switch (channels) {
749 /*
750 * Do not handle stereo output in Multi-channel cases
751 * Stereo case is handled in normal playback path
752 */
753 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700754 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
757 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
759 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 break;
761 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769 break;
770 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700771 ALOGE("HDMI does not support multi channel playback");
772 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773 break;
774 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700775 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776}
777
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800778audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
779 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700780{
781 struct audio_usecase *usecase;
782 struct listnode *node;
783
784 list_for_each(node, &adev->usecase_list) {
785 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800786 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700787 ALOGV("%s: usecase id %d", __func__, usecase->id);
788 return usecase->id;
789 }
790 }
791 return USECASE_INVALID;
792}
793
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700794struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700796{
797 struct audio_usecase *usecase;
798 struct listnode *node;
799
800 list_for_each(node, &adev->usecase_list) {
801 usecase = node_to_item(node, struct audio_usecase, list);
802 if (usecase->id == uc_id)
803 return usecase;
804 }
805 return NULL;
806}
807
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700808int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800810 snd_device_t out_snd_device = SND_DEVICE_NONE;
811 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 struct audio_usecase *usecase = NULL;
813 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800814 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800815 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800816 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800817 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700818 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 usecase = get_usecase_from_list(adev, uc_id);
821 if (usecase == NULL) {
822 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
823 return -EINVAL;
824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800825
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800826 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800827 (usecase->type == VOIP_CALL) ||
828 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700829 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800830 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700831 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 usecase->devices = usecase->stream.out->devices;
833 } else {
834 /*
835 * If the voice call is active, use the sound devices of voice call usecase
836 * so that it would not result any device switch. All the usecases will
837 * be switched to new device when select_devices() is called for voice call
838 * usecase. This is to avoid switching devices for voice call when
839 * check_usecases_codec_backend() is called below.
840 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700841 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800843 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700844 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
845 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 in_snd_device = vc_usecase->in_snd_device;
847 out_snd_device = vc_usecase->out_snd_device;
848 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 } else if (voice_extn_compress_voip_is_active(adev)) {
850 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700851 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530852 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700853 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800854 in_snd_device = voip_usecase->in_snd_device;
855 out_snd_device = voip_usecase->out_snd_device;
856 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800857 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800858 hfp_ucid = audio_extn_hfp_get_usecase();
859 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700860 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800861 in_snd_device = hfp_usecase->in_snd_device;
862 out_snd_device = hfp_usecase->out_snd_device;
863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 }
865 if (usecase->type == PCM_PLAYBACK) {
866 usecase->devices = usecase->stream.out->devices;
867 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700868 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800870 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700871 if (usecase->stream.out == adev->primary_output &&
872 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800873 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
874 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700875 select_devices(adev, adev->active_input->usecase);
876 }
877 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 } else if (usecase->type == PCM_CAPTURE) {
879 usecase->devices = usecase->stream.in->device;
880 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700881 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700882 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530883 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
884 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
885 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
886 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700887 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800888 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700889 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
890 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700892 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 }
895 }
896
897 if (out_snd_device == usecase->out_snd_device &&
898 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800899 return 0;
900 }
901
sangwoobc677242013-08-08 16:53:43 +0900902 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700903 out_snd_device, platform_get_snd_device_name(out_snd_device),
904 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906 /*
907 * Limitation: While in call, to do a device switch we need to disable
908 * and enable both RX and TX devices though one of them is same as current
909 * device.
910 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700911 if ((usecase->type == VOICE_CALL) &&
912 (usecase->in_snd_device != SND_DEVICE_NONE) &&
913 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700914 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700915 /* Disable sidetone only if voice call already exists */
916 if (voice_is_call_state_active(adev))
917 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800918 }
919
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 /* Disable current sound devices */
921 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700922 disable_audio_route(adev, usecase);
923 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800924 }
925
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700927 disable_audio_route(adev, usecase);
928 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929 }
930
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800931 /* Applicable only on the targets that has external modem.
932 * New device information should be sent to modem before enabling
933 * the devices to reduce in-call device switch time.
934 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700935 if ((usecase->type == VOICE_CALL) &&
936 (usecase->in_snd_device != SND_DEVICE_NONE) &&
937 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800938 status = platform_switch_voice_call_enable_device_config(adev->platform,
939 out_snd_device,
940 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700941 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800942
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 /* Enable new sound devices */
944 if (out_snd_device != SND_DEVICE_NONE) {
945 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
946 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700947 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948 }
949
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 if (in_snd_device != SND_DEVICE_NONE) {
951 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700952 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700953 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954
Avinash Vaish71a8b972014-07-24 15:36:33 +0530955 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700956 status = platform_switch_voice_call_device_post(adev->platform,
957 out_snd_device,
958 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530959 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700960 /* Enable sidetone only if voice call already exists */
961 if (voice_is_call_state_active(adev))
962 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530963 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800964
sangwoo170731f2013-06-08 15:36:36 +0900965 usecase->in_snd_device = in_snd_device;
966 usecase->out_snd_device = out_snd_device;
967
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530968 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700969 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530970 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700971 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530972 usecase->stream.out->flags,
973 usecase->stream.out->format,
974 usecase->stream.out->sample_rate,
975 usecase->stream.out->bit_width,
976 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700977 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530978 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700979
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900981
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800982 /* Applicable only on the targets that has external modem.
983 * Enable device command should be sent to modem only after
984 * enabling voice call mixer controls
985 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700986 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800987 status = platform_switch_voice_call_usecase_route_post(adev->platform,
988 out_snd_device,
989 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530990 ALOGD("%s: done",__func__);
991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 return status;
993}
994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995static int stop_input_stream(struct stream_in *in)
996{
997 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998 struct audio_usecase *uc_info;
999 struct audio_device *adev = in->dev;
1000
Eric Laurentc8400632013-02-14 19:04:54 -08001001 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002
Eric Laurent994a6932013-07-17 11:51:42 -07001003 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005 uc_info = get_usecase_from_list(adev, in->usecase);
1006 if (uc_info == NULL) {
1007 ALOGE("%s: Could not find the usecase (%d) in the list",
1008 __func__, in->usecase);
1009 return -EINVAL;
1010 }
1011
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001012 /* Close in-call recording streams */
1013 voice_check_and_stop_incall_rec_usecase(adev, in);
1014
Eric Laurent150dbfe2013-02-27 14:31:02 -08001015 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001016 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017
1018 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001019 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001021 list_remove(&uc_info->list);
1022 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023
Eric Laurent994a6932013-07-17 11:51:42 -07001024 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 return ret;
1026}
1027
1028int start_input_stream(struct stream_in *in)
1029{
1030 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001031 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 struct audio_usecase *uc_info;
1033 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301034 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035
Mingming Yine62d7842013-10-25 16:26:03 -07001036 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301037 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1038 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001039
Naresh Tanniru80659832014-06-04 18:17:56 +05301040
1041 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301042 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301043 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301044 goto error_config;
1045 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301046
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001047 /* Check if source matches incall recording usecase criteria */
1048 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1049 if (ret)
1050 goto error_config;
1051 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001052 ALOGD("%s: Updated usecase(%d: %s)",
1053 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001054
Eric Laurentb23d5282013-05-14 15:27:20 -07001055 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056 if (in->pcm_device_id < 0) {
1057 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1058 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001059 ret = -EINVAL;
1060 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062
1063 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001065
1066 if (!uc_info) {
1067 ret = -ENOMEM;
1068 goto error_config;
1069 }
1070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 uc_info->id = in->usecase;
1072 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001073 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 uc_info->devices = in->device;
1075 uc_info->in_snd_device = SND_DEVICE_NONE;
1076 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001078 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301079 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081
Eric Laurentc8400632013-02-14 19:04:54 -08001082 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001083 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1084
1085 unsigned int flags = PCM_IN;
1086 unsigned int pcm_open_retry_count = 0;
1087
1088 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1089 flags |= PCM_MMAP | PCM_NOIRQ;
1090 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1091 }
1092
1093 while (1) {
1094 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1095 flags, &in->config);
1096 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1097 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1098 if (in->pcm != NULL) {
1099 pcm_close(in->pcm);
1100 in->pcm = NULL;
1101 }
1102 if (pcm_open_retry_count-- == 0) {
1103 ret = -EIO;
1104 goto error_open;
1105 }
1106 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1107 continue;
1108 }
1109 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301111 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301112
Eric Laurent994a6932013-07-17 11:51:42 -07001113 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001114 return ret;
1115
1116error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301118 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001119
1120error_config:
1121 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001123
1124 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125}
1126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001127/* must be called with out->lock locked */
1128static int send_offload_cmd_l(struct stream_out* out, int command)
1129{
1130 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1131
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001132 if (!cmd) {
1133 ALOGE("failed to allocate mem for command 0x%x", command);
1134 return -ENOMEM;
1135 }
1136
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001137 ALOGVV("%s %d", __func__, command);
1138
1139 cmd->cmd = command;
1140 list_add_tail(&out->offload_cmd_list, &cmd->node);
1141 pthread_cond_signal(&out->offload_cond);
1142 return 0;
1143}
1144
1145/* must be called iwth out->lock locked */
1146static void stop_compressed_output_l(struct stream_out *out)
1147{
1148 out->offload_state = OFFLOAD_STATE_IDLE;
1149 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001150 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001151 if (out->compr != NULL) {
1152 compress_stop(out->compr);
1153 while (out->offload_thread_blocked) {
1154 pthread_cond_wait(&out->cond, &out->lock);
1155 }
1156 }
1157}
1158
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001159bool is_offload_usecase(audio_usecase_t uc_id)
1160{
1161 unsigned int i;
1162 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1163 if (uc_id == offload_usecases[i])
1164 return true;
1165 }
1166 return false;
1167}
1168
1169static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1170{
1171 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1172 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1173 char value[PROPERTY_VALUE_MAX] = {0};
1174
1175 property_get("audio.offload.multiple.enabled", value, NULL);
1176 if (!(atoi(value) || !strncmp("true", value, 4)))
1177 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1178
1179 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1180 for (i = 0; i < num_usecase; i++) {
1181 if (!(adev->offload_usecases_state & (0x1<<i))) {
1182 adev->offload_usecases_state |= 0x1 << i;
1183 ret = offload_usecases[i];
1184 break;
1185 }
1186 }
1187 ALOGV("%s: offload usecase is %d", __func__, ret);
1188 return ret;
1189}
1190
1191static void free_offload_usecase(struct audio_device *adev,
1192 audio_usecase_t uc_id)
1193{
1194 unsigned int i;
1195 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1196 if (offload_usecases[i] == uc_id) {
1197 adev->offload_usecases_state &= ~(0x1<<i);
1198 break;
1199 }
1200 }
1201 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1202}
1203
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001204static void *offload_thread_loop(void *context)
1205{
1206 struct stream_out *out = (struct stream_out *) context;
1207 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001208 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001210 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1211 set_sched_policy(0, SP_FOREGROUND);
1212 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1213
1214 ALOGV("%s", __func__);
1215 pthread_mutex_lock(&out->lock);
1216 for (;;) {
1217 struct offload_cmd *cmd = NULL;
1218 stream_callback_event_t event;
1219 bool send_callback = false;
1220
1221 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1222 __func__, list_empty(&out->offload_cmd_list),
1223 out->offload_state);
1224 if (list_empty(&out->offload_cmd_list)) {
1225 ALOGV("%s SLEEPING", __func__);
1226 pthread_cond_wait(&out->offload_cond, &out->lock);
1227 ALOGV("%s RUNNING", __func__);
1228 continue;
1229 }
1230
1231 item = list_head(&out->offload_cmd_list);
1232 cmd = node_to_item(item, struct offload_cmd, node);
1233 list_remove(item);
1234
1235 ALOGVV("%s STATE %d CMD %d out->compr %p",
1236 __func__, out->offload_state, cmd->cmd, out->compr);
1237
1238 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1239 free(cmd);
1240 break;
1241 }
1242
1243 if (out->compr == NULL) {
1244 ALOGE("%s: Compress handle is NULL", __func__);
1245 pthread_cond_signal(&out->cond);
1246 continue;
1247 }
1248 out->offload_thread_blocked = true;
1249 pthread_mutex_unlock(&out->lock);
1250 send_callback = false;
1251 switch(cmd->cmd) {
1252 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001253 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001254 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001255 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001256 send_callback = true;
1257 event = STREAM_CBK_EVENT_WRITE_READY;
1258 break;
1259 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001260 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301261 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001262 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301263 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001264 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301265 if (ret < 0)
1266 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301267 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301268 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001269 compress_drain(out->compr);
1270 else
1271 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301272 if (ret != -ENETRESET) {
1273 send_callback = true;
1274 event = STREAM_CBK_EVENT_DRAIN_READY;
1275 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1276 } else
1277 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001278 break;
1279 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001280 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001281 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001282 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001283 send_callback = true;
1284 event = STREAM_CBK_EVENT_DRAIN_READY;
1285 break;
1286 default:
1287 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1288 break;
1289 }
1290 pthread_mutex_lock(&out->lock);
1291 out->offload_thread_blocked = false;
1292 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001293 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001294 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001296 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001297 free(cmd);
1298 }
1299
1300 pthread_cond_signal(&out->cond);
1301 while (!list_empty(&out->offload_cmd_list)) {
1302 item = list_head(&out->offload_cmd_list);
1303 list_remove(item);
1304 free(node_to_item(item, struct offload_cmd, node));
1305 }
1306 pthread_mutex_unlock(&out->lock);
1307
1308 return NULL;
1309}
1310
1311static int create_offload_callback_thread(struct stream_out *out)
1312{
1313 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1314 list_init(&out->offload_cmd_list);
1315 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1316 offload_thread_loop, out);
1317 return 0;
1318}
1319
1320static int destroy_offload_callback_thread(struct stream_out *out)
1321{
1322 pthread_mutex_lock(&out->lock);
1323 stop_compressed_output_l(out);
1324 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1325
1326 pthread_mutex_unlock(&out->lock);
1327 pthread_join(out->offload_thread, (void **) NULL);
1328 pthread_cond_destroy(&out->offload_cond);
1329
1330 return 0;
1331}
1332
Eric Laurent07eeafd2013-10-06 12:52:49 -07001333static bool allow_hdmi_channel_config(struct audio_device *adev)
1334{
1335 struct listnode *node;
1336 struct audio_usecase *usecase;
1337 bool ret = true;
1338
1339 list_for_each(node, &adev->usecase_list) {
1340 usecase = node_to_item(node, struct audio_usecase, list);
1341 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1342 /*
1343 * If voice call is already existing, do not proceed further to avoid
1344 * disabling/enabling both RX and TX devices, CSD calls, etc.
1345 * Once the voice call done, the HDMI channels can be configured to
1346 * max channels of remaining use cases.
1347 */
1348 if (usecase->id == USECASE_VOICE_CALL) {
1349 ALOGD("%s: voice call is active, no change in HDMI channels",
1350 __func__);
1351 ret = false;
1352 break;
1353 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1354 ALOGD("%s: multi channel playback is active, "
1355 "no change in HDMI channels", __func__);
1356 ret = false;
1357 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001358 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001359 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001360 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1361 ", no change in HDMI channels", __func__,
1362 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001363 ret = false;
1364 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001365 }
1366 }
1367 }
1368 return ret;
1369}
1370
1371static int check_and_set_hdmi_channels(struct audio_device *adev,
1372 unsigned int channels)
1373{
1374 struct listnode *node;
1375 struct audio_usecase *usecase;
1376
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001377 unsigned int supported_channels = platform_edid_get_max_channels(
1378 adev->platform);
1379 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001380 /* Check if change in HDMI channel config is allowed */
1381 if (!allow_hdmi_channel_config(adev))
1382 return 0;
1383
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001384 if (channels > supported_channels)
1385 channels = supported_channels;
1386
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001388 ALOGD("%s: Requested channels are same as current channels(%d)",
1389 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001390 return 0;
1391 }
1392
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001393 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001394 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001395 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001396 adev->cur_hdmi_channels = channels;
1397
1398 /*
1399 * Deroute all the playback streams routed to HDMI so that
1400 * the back end is deactivated. Note that backend will not
1401 * be deactivated if any one stream is connected to it.
1402 */
1403 list_for_each(node, &adev->usecase_list) {
1404 usecase = node_to_item(node, struct audio_usecase, list);
1405 if (usecase->type == PCM_PLAYBACK &&
1406 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001407 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001408 }
1409 }
1410
1411 /*
1412 * Enable all the streams disabled above. Now the HDMI backend
1413 * will be activated with new channel configuration
1414 */
1415 list_for_each(node, &adev->usecase_list) {
1416 usecase = node_to_item(node, struct audio_usecase, list);
1417 if (usecase->type == PCM_PLAYBACK &&
1418 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001419 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001420 }
1421 }
1422
1423 return 0;
1424}
1425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426static int stop_output_stream(struct stream_out *out)
1427{
1428 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 struct audio_usecase *uc_info;
1430 struct audio_device *adev = out->dev;
1431
Eric Laurent994a6932013-07-17 11:51:42 -07001432 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001433 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 uc_info = get_usecase_from_list(adev, out->usecase);
1435 if (uc_info == NULL) {
1436 ALOGE("%s: Could not find the usecase (%d) in the list",
1437 __func__, out->usecase);
1438 return -EINVAL;
1439 }
1440
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001441 if (is_offload_usecase(out->usecase) &&
1442 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001443 if (adev->visualizer_stop_output != NULL)
1444 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001445
1446 audio_extn_dts_remove_state_notifier_node(out->usecase);
1447
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001448 if (adev->offload_effects_stop_output != NULL)
1449 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1450 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001451
Eric Laurent150dbfe2013-02-27 14:31:02 -08001452 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001453 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454
1455 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001456 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001458 list_remove(&uc_info->list);
1459 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001461 if (is_offload_usecase(out->usecase) &&
1462 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1463 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1464 ALOGV("Disable passthrough , reset mixer to pcm");
1465 /* NO_PASSTHROUGH */
1466 out->compr_config.codec->compr_passthr = 0;
1467 audio_extn_dolby_set_hdmi_config(adev, out);
1468 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1469 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001470 /* Must be called after removing the usecase from list */
1471 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1472 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1473
Eric Laurent994a6932013-07-17 11:51:42 -07001474 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 return ret;
1476}
1477
1478int start_output_stream(struct stream_out *out)
1479{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001481 int sink_channels = 0;
1482 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 struct audio_usecase *uc_info;
1484 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301485 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001487 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1488 ret = -EINVAL;
1489 goto error_config;
1490 }
1491
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301492 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1493 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1494 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301495
Naresh Tanniru80659832014-06-04 18:17:56 +05301496 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301497 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301498 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301499 goto error_config;
1500 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301501
Eric Laurentb23d5282013-05-14 15:27:20 -07001502 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503 if (out->pcm_device_id < 0) {
1504 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1505 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001506 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001507 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 }
1509
1510 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001511
1512 if (!uc_info) {
1513 ret = -ENOMEM;
1514 goto error_config;
1515 }
1516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 uc_info->id = out->usecase;
1518 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001519 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001520 uc_info->devices = out->devices;
1521 uc_info->in_snd_device = SND_DEVICE_NONE;
1522 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001523 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001524 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001525 if (is_offload_usecase(out->usecase)) {
1526 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001527 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1528 }
1529 }
Mingming Yin9c041392014-05-01 15:37:31 -07001530 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1531 if (!strncmp("true", prop_value, 4)) {
1532 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001533 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1534 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001535 check_and_set_hdmi_channels(adev, sink_channels);
1536 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001537 if (is_offload_usecase(out->usecase)) {
1538 unsigned int ch_count = out->compr_config.codec->ch_in;
1539 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1540 /* backend channel config for passthrough stream is stereo */
1541 ch_count = 2;
1542 check_and_set_hdmi_channels(adev, ch_count);
1543 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001544 check_and_set_hdmi_channels(adev, out->config.channels);
1545 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001546 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001547 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001548 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001550 select_devices(adev, out->usecase);
1551
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001552 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1553 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001554 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001555 unsigned int flags = PCM_OUT;
1556 unsigned int pcm_open_retry_count = 0;
1557 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1558 flags |= PCM_MMAP | PCM_NOIRQ;
1559 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1560 } else
1561 flags |= PCM_MONOTONIC;
1562
1563 while (1) {
1564 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1565 flags, &out->config);
1566 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1567 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1568 if (out->pcm != NULL) {
1569 pcm_close(out->pcm);
1570 out->pcm = NULL;
1571 }
1572 if (pcm_open_retry_count-- == 0) {
1573 ret = -EIO;
1574 goto error_open;
1575 }
1576 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1577 continue;
1578 }
1579 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001581 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1582 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001584 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1585 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001587 out->compr = compress_open(adev->snd_card,
1588 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 COMPRESS_IN, &out->compr_config);
1590 if (out->compr && !is_compress_ready(out->compr)) {
1591 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1592 compress_close(out->compr);
1593 out->compr = NULL;
1594 ret = -EIO;
1595 goto error_open;
1596 }
1597 if (out->offload_callback)
1598 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001599
Fred Oh3f43e742015-03-04 18:42:34 -08001600 /* Since small bufs uses blocking writes, a write will be blocked
1601 for the default max poll time (20s) in the event of an SSR.
1602 Reduce the poll time to observe and deal with SSR faster.
1603 */
1604 if (out->use_small_bufs) {
1605 compress_set_max_poll_wait(out->compr, 1000);
1606 }
1607
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001608 audio_extn_dts_create_state_notifier_node(out->usecase);
1609 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1610 popcount(out->channel_mask),
1611 out->playback_started);
1612
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001613#ifdef DS1_DOLBY_DDP_ENABLED
1614 if (audio_extn_is_dolby_format(out->format))
1615 audio_extn_dolby_send_ddp_endp_params(adev);
1616#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001617 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1618 if (adev->visualizer_start_output != NULL)
1619 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1620 if (adev->offload_effects_start_output != NULL)
1621 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001622 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
Eric Laurent994a6932013-07-17 11:51:42 -07001625 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001627error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001629error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631}
1632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633static int check_input_parameters(uint32_t sample_rate,
1634 audio_format_t format,
1635 int channel_count)
1636{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001637 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001639 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001640 !voice_extn_compress_voip_is_format_supported(format) &&
1641 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001642
1643 switch (channel_count) {
1644 case 1:
1645 case 2:
1646 case 6:
1647 break;
1648 default:
1649 ret = -EINVAL;
1650 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651
1652 switch (sample_rate) {
1653 case 8000:
1654 case 11025:
1655 case 12000:
1656 case 16000:
1657 case 22050:
1658 case 24000:
1659 case 32000:
1660 case 44100:
1661 case 48000:
1662 break;
1663 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001664 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 }
1666
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668}
1669
1670static size_t get_input_buffer_size(uint32_t sample_rate,
1671 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001672 int channel_count,
1673 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674{
1675 size_t size = 0;
1676
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001677 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1678 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001680 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001681 if (is_low_latency)
1682 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001683 /* ToDo: should use frame_size computed based on the format and
1684 channel_count here. */
1685 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001687 /* make sure the size is multiple of 32 bytes
1688 * At 48 kHz mono 16-bit PCM:
1689 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1690 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1691 */
1692 size += 0x1f;
1693 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001694
1695 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696}
1697
1698static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1699{
1700 struct stream_out *out = (struct stream_out *)stream;
1701
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001702 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703}
1704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001705static int out_set_sample_rate(struct audio_stream *stream __unused,
1706 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707{
1708 return -ENOSYS;
1709}
1710
1711static size_t out_get_buffer_size(const struct audio_stream *stream)
1712{
1713 struct stream_out *out = (struct stream_out *)stream;
1714
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001715 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001716 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001717 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1718 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001720 return out->config.period_size *
1721 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722}
1723
1724static uint32_t out_get_channels(const struct audio_stream *stream)
1725{
1726 struct stream_out *out = (struct stream_out *)stream;
1727
1728 return out->channel_mask;
1729}
1730
1731static audio_format_t out_get_format(const struct audio_stream *stream)
1732{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 struct stream_out *out = (struct stream_out *)stream;
1734
1735 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736}
1737
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001738static int out_set_format(struct audio_stream *stream __unused,
1739 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740{
1741 return -ENOSYS;
1742}
1743
1744static int out_standby(struct audio_stream *stream)
1745{
1746 struct stream_out *out = (struct stream_out *)stream;
1747 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301749 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1750 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001751 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1752 /* Ignore standby in case of voip call because the voip output
1753 * stream is closed in adev_close_output_stream()
1754 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301755 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001756 return 0;
1757 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001761 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001763 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 if (out->pcm) {
1765 pcm_close(out->pcm);
1766 out->pcm = NULL;
1767 }
1768 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001769 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001771 out->gapless_mdata.encoder_delay = 0;
1772 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 if (out->compr != NULL) {
1774 compress_close(out->compr);
1775 out->compr = NULL;
1776 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001777 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001779 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 }
1781 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001782 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 return 0;
1784}
1785
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001786static int out_dump(const struct audio_stream *stream __unused,
1787 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788{
1789 return 0;
1790}
1791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001792static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1793{
1794 int ret = 0;
1795 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001796 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001797
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001799 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001800 return -EINVAL;
1801 }
1802
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001803 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1804 if (ret >= 0) {
1805 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1806 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1807 ALOGV("ADTS format is set in offload mode");
1808 }
1809 out->send_new_metadata = 1;
1810 }
1811
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301812 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001813
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001814 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1815 if(ret >= 0)
1816 is_meta_data_params = true;
1817 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301818 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001819 is_meta_data_params = true;
1820 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301821 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001822 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1824 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001825 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301826 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001828 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1829 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001830 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301831 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 }
1833
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001834 if(!is_meta_data_params) {
1835 ALOGV("%s: Not gapless meta data params", __func__);
1836 return 0;
1837 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838 out->send_new_metadata = 1;
1839 ALOGV("%s new encoder delay %u and padding %u", __func__,
1840 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1841
1842 return 0;
1843}
1844
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001845static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1846{
1847 return out == adev->primary_output || out == adev->voice_tx_output;
1848}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1851{
1852 struct stream_out *out = (struct stream_out *)stream;
1853 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001854 struct audio_usecase *usecase;
1855 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 struct str_parms *parms;
1857 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001858 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001859 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860
sangwoobc677242013-08-08 16:53:43 +09001861 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001862 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301864 if (!parms)
1865 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001866 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1867 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001870 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301873 * When HDMI cable is unplugged/usb hs is disconnected the
1874 * music playback is paused and the policy manager sends routing=0
1875 * But the audioflingercontinues to write data until standby time
1876 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 * Avoid this by routing audio to speaker until standby.
1878 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301879 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1880 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001882 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1883 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001884 }
1885
1886 /*
1887 * select_devices() call below switches all the usecases on the same
1888 * backend to the new device. Refer to check_usecases_codec_backend() in
1889 * the select_devices(). But how do we undo this?
1890 *
1891 * For example, music playback is active on headset (deep-buffer usecase)
1892 * and if we go to ringtones and select a ringtone, low-latency usecase
1893 * will be started on headset+speaker. As we can't enable headset+speaker
1894 * and headset devices at the same time, select_devices() switches the music
1895 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1896 * So when the ringtone playback is completed, how do we undo the same?
1897 *
1898 * We are relying on the out_set_parameters() call on deep-buffer output,
1899 * once the ringtone playback is ended.
1900 * NOTE: We should not check if the current devices are same as new devices.
1901 * Because select_devices() must be called to switch back the music
1902 * playback to headset.
1903 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001904 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 out->devices = val;
1906
1907 if (!out->standby)
1908 select_devices(adev, out->usecase);
1909
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001910 if (output_drives_call(adev, out)) {
1911 if(!voice_is_in_call(adev)) {
1912 if (adev->mode == AUDIO_MODE_IN_CALL) {
1913 adev->current_call_output = out;
1914 ret = voice_start_call(adev);
1915 }
1916 } else {
1917 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001918 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001919 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001920 }
1921 }
1922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001924 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001926
1927 if (out == adev->primary_output) {
1928 pthread_mutex_lock(&adev->lock);
1929 audio_extn_set_parameters(adev, parms);
1930 pthread_mutex_unlock(&adev->lock);
1931 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001932 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001933 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001934 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001935
1936 audio_extn_dts_create_state_notifier_node(out->usecase);
1937 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1938 popcount(out->channel_mask),
1939 out->playback_started);
1940
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001941 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001942 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301945error:
Eric Laurent994a6932013-07-17 11:51:42 -07001946 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947 return ret;
1948}
1949
1950static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1951{
1952 struct stream_out *out = (struct stream_out *)stream;
1953 struct str_parms *query = str_parms_create_str(keys);
1954 char *str;
1955 char value[256];
1956 struct str_parms *reply = str_parms_create();
1957 size_t i, j;
1958 int ret;
1959 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001960
1961 if (!query || !reply) {
1962 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1963 return NULL;
1964 }
1965
Eric Laurent994a6932013-07-17 11:51:42 -07001966 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1968 if (ret >= 0) {
1969 value[0] = '\0';
1970 i = 0;
1971 while (out->supported_channel_masks[i] != 0) {
1972 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1973 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1974 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001975 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001977 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 first = false;
1979 break;
1980 }
1981 }
1982 i++;
1983 }
1984 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1985 str = str_parms_to_str(reply);
1986 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001987 voice_extn_out_get_parameters(out, query, reply);
1988 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001989 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001990 free(str);
1991 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001992 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001994
1995 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1996 if (ret >= 0) {
1997 value[0] = '\0';
1998 i = 0;
1999 first = true;
2000 while (out->supported_formats[i] != 0) {
2001 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2002 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2003 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002004 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002005 }
2006 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2007 first = false;
2008 break;
2009 }
2010 }
2011 i++;
2012 }
2013 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2014 str = str_parms_to_str(reply);
2015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 str_parms_destroy(query);
2017 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 return str;
2020}
2021
2022static uint32_t out_get_latency(const struct audio_stream_out *stream)
2023{
2024 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002025 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026
Alexy Josephaa54c872014-12-03 02:46:47 -08002027 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002028 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002029 } else {
2030 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002032 }
2033
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302034 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002035 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036}
2037
2038static int out_set_volume(struct audio_stream_out *stream, float left,
2039 float right)
2040{
Eric Laurenta9024de2013-04-04 09:19:12 -07002041 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 int volume[2];
2043
Eric Laurenta9024de2013-04-04 09:19:12 -07002044 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2045 /* only take left channel into account: the API is for stereo anyway */
2046 out->muted = (left == 0.0f);
2047 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002048 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002049 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2050 /*
2051 * Set mute or umute on HDMI passthrough stream.
2052 * Only take left channel into account.
2053 * Mute is 0 and unmute 1
2054 */
2055 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2056 } else {
2057 char mixer_ctl_name[128];
2058 struct audio_device *adev = out->dev;
2059 struct mixer_ctl *ctl;
2060 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002061 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002063 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2064 "Compress Playback %d Volume", pcm_device_id);
2065 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2066 if (!ctl) {
2067 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2068 __func__, mixer_ctl_name);
2069 return -EINVAL;
2070 }
2071 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2072 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2073 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2074 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 return -ENOSYS;
2079}
2080
2081static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2082 size_t bytes)
2083{
2084 struct stream_out *out = (struct stream_out *)stream;
2085 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302086 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002087 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302090
Naresh Tanniru80659832014-06-04 18:17:56 +05302091 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002092 // increase written size during SSR to avoid mismatch
2093 // with the written frames count in AF
2094 if (!is_offload_usecase(out->usecase))
2095 out->written += bytes / (out->config.channels * sizeof(short));
2096
Naresh Tanniru80659832014-06-04 18:17:56 +05302097 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302098 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302099 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302100 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002101 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302102 //during SSR for compress usecase we should return error to flinger
2103 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2104 pthread_mutex_unlock(&out->lock);
2105 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302106 }
2107 }
2108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002110 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002111 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002112 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2113 ret = voice_extn_compress_voip_start_output_stream(out);
2114 else
2115 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002116 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002119 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 goto exit;
2121 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002124 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002125 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002127 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2129 out->send_new_metadata = 0;
2130 }
2131
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302133 if (ret < 0)
2134 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002135 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002136 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302137 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 } else if (-ENETRESET == ret) {
2140 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2141 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2142 pthread_mutex_unlock(&out->lock);
2143 out_standby(&out->stream.common);
2144 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302146 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002147 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002148 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 out->playback_started = 1;
2150 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002151
2152 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2153 popcount(out->channel_mask),
2154 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 }
2156 pthread_mutex_unlock(&out->lock);
2157 return ret;
2158 } else {
2159 if (out->pcm) {
2160 if (out->muted)
2161 memset((void *)buffer, 0, bytes);
2162 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002163 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2164 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2165 else
2166 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302167 if (ret < 0)
2168 ret = -errno;
2169 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002170 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 }
2173
2174exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302175 /* ToDo: There may be a corner case when SSR happens back to back during
2176 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302177 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302178 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302179 }
2180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 pthread_mutex_unlock(&out->lock);
2182
2183 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002184 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002185 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302186 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302187 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302188 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302189 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302190 out->standby = true;
2191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002193 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302194 out_get_sample_rate(&out->stream.common));
2195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 }
2197 return bytes;
2198}
2199
2200static int out_get_render_position(const struct audio_stream_out *stream,
2201 uint32_t *dsp_frames)
2202{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002203 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302204 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002205
2206 if (dsp_frames == NULL)
2207 return -EINVAL;
2208
2209 *dsp_frames = 0;
2210 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002211 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212 pthread_mutex_lock(&out->lock);
2213 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302214 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302216 if (ret < 0)
2217 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 ALOGVV("%s rendered frames %d sample_rate %d",
2219 __func__, *dsp_frames, out->sample_rate);
2220 }
2221 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 if (-ENETRESET == ret) {
2223 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2224 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2225 return -EINVAL;
2226 } else if(ret < 0) {
2227 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2228 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302229 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2230 /*
2231 * Handle corner case where compress session is closed during SSR
2232 * and timestamp is queried
2233 */
2234 ALOGE(" ERROR: sound card not active, return error");
2235 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302236 } else {
2237 return 0;
2238 }
Zhou Song32a556e2015-05-05 10:46:56 +08002239 } else if (audio_is_linear_pcm(out->format)) {
2240 *dsp_frames = out->written;
2241 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 } else
2243 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244}
2245
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002246static int out_add_audio_effect(const struct audio_stream *stream __unused,
2247 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248{
2249 return 0;
2250}
2251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002252static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2253 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 return 0;
2256}
2257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002258static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2259 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260{
2261 return -EINVAL;
2262}
2263
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002264static int out_get_presentation_position(const struct audio_stream_out *stream,
2265 uint64_t *frames, struct timespec *timestamp)
2266{
2267 struct stream_out *out = (struct stream_out *)stream;
2268 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002269 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002270
2271 pthread_mutex_lock(&out->lock);
2272
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002273 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002274 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302275 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002276 &out->sample_rate);
2277 ALOGVV("%s rendered frames %ld sample_rate %d",
2278 __func__, dsp_frames, out->sample_rate);
2279 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302280 if (ret < 0)
2281 ret = -errno;
2282 if (-ENETRESET == ret) {
2283 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2284 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2285 ret = -EINVAL;
2286 } else
2287 ret = 0;
2288
Eric Laurent949a0892013-09-20 09:20:13 -07002289 /* this is the best we can do */
2290 clock_gettime(CLOCK_MONOTONIC, timestamp);
2291 }
2292 } else {
2293 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002294 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002295 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2296 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002297 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002298 // This adjustment accounts for buffering after app processor.
2299 // It is based on estimated DSP latency per use case, rather than exact.
2300 signed_frames -=
2301 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2302
Eric Laurent949a0892013-09-20 09:20:13 -07002303 // It would be unusual for this value to be negative, but check just in case ...
2304 if (signed_frames >= 0) {
2305 *frames = signed_frames;
2306 ret = 0;
2307 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002308 }
2309 }
2310 }
2311
2312 pthread_mutex_unlock(&out->lock);
2313
2314 return ret;
2315}
2316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317static int out_set_callback(struct audio_stream_out *stream,
2318 stream_callback_t callback, void *cookie)
2319{
2320 struct stream_out *out = (struct stream_out *)stream;
2321
2322 ALOGV("%s", __func__);
2323 pthread_mutex_lock(&out->lock);
2324 out->offload_callback = callback;
2325 out->offload_cookie = cookie;
2326 pthread_mutex_unlock(&out->lock);
2327 return 0;
2328}
2329
2330static int out_pause(struct audio_stream_out* stream)
2331{
2332 struct stream_out *out = (struct stream_out *)stream;
2333 int status = -ENOSYS;
2334 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002335 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002336 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 pthread_mutex_lock(&out->lock);
2338 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302339 struct audio_device *adev = out->dev;
2340 int snd_scard_state = get_snd_card_state(adev);
2341
2342 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2343 status = compress_pause(out->compr);
2344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002346
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302347 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002348 audio_extn_dts_notify_playback_state(out->usecase, 0,
2349 out->sample_rate, popcount(out->channel_mask),
2350 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 }
2352 pthread_mutex_unlock(&out->lock);
2353 }
2354 return status;
2355}
2356
2357static int out_resume(struct audio_stream_out* stream)
2358{
2359 struct stream_out *out = (struct stream_out *)stream;
2360 int status = -ENOSYS;
2361 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002362 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002363 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 status = 0;
2365 pthread_mutex_lock(&out->lock);
2366 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302367 struct audio_device *adev = out->dev;
2368 int snd_scard_state = get_snd_card_state(adev);
2369
2370 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2371 status = compress_resume(out->compr);
2372
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302375 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002376 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2377 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002378 }
2379 pthread_mutex_unlock(&out->lock);
2380 }
2381 return status;
2382}
2383
2384static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2385{
2386 struct stream_out *out = (struct stream_out *)stream;
2387 int status = -ENOSYS;
2388 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002389 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 pthread_mutex_lock(&out->lock);
2391 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2392 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2393 else
2394 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2395 pthread_mutex_unlock(&out->lock);
2396 }
2397 return status;
2398}
2399
2400static int out_flush(struct audio_stream_out* stream)
2401{
2402 struct stream_out *out = (struct stream_out *)stream;
2403 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002404 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002405 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 pthread_mutex_lock(&out->lock);
2407 stop_compressed_output_l(out);
2408 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002409 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 return 0;
2411 }
2412 return -ENOSYS;
2413}
2414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415/** audio_stream_in implementation **/
2416static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2417{
2418 struct stream_in *in = (struct stream_in *)stream;
2419
2420 return in->config.rate;
2421}
2422
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002423static int in_set_sample_rate(struct audio_stream *stream __unused,
2424 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425{
2426 return -ENOSYS;
2427}
2428
2429static size_t in_get_buffer_size(const struct audio_stream *stream)
2430{
2431 struct stream_in *in = (struct stream_in *)stream;
2432
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002433 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2434 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002435 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2436 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002437
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002438 return in->config.period_size *
2439 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440}
2441
2442static uint32_t in_get_channels(const struct audio_stream *stream)
2443{
2444 struct stream_in *in = (struct stream_in *)stream;
2445
2446 return in->channel_mask;
2447}
2448
2449static audio_format_t in_get_format(const struct audio_stream *stream)
2450{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002451 struct stream_in *in = (struct stream_in *)stream;
2452
2453 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454}
2455
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002456static int in_set_format(struct audio_stream *stream __unused,
2457 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458{
2459 return -ENOSYS;
2460}
2461
2462static int in_standby(struct audio_stream *stream)
2463{
2464 struct stream_in *in = (struct stream_in *)stream;
2465 struct audio_device *adev = in->dev;
2466 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302467 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2468 stream, in->usecase, use_case_table[in->usecase]);
2469
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002470 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2471 /* Ignore standby in case of voip call because the voip input
2472 * stream is closed in adev_close_input_stream()
2473 */
2474 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2475 return status;
2476 }
2477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002479 if (!in->standby && in->is_st_session) {
2480 ALOGD("%s: sound trigger pcm stop lab", __func__);
2481 audio_extn_sound_trigger_stop_lab(in);
2482 in->standby = 1;
2483 }
2484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002486 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002488 if (in->pcm) {
2489 pcm_close(in->pcm);
2490 in->pcm = NULL;
2491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002493 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 }
2495 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002496 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 return status;
2498}
2499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002500static int in_dump(const struct audio_stream *stream __unused,
2501 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
2503 return 0;
2504}
2505
2506static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2507{
2508 struct stream_in *in = (struct stream_in *)stream;
2509 struct audio_device *adev = in->dev;
2510 struct str_parms *parms;
2511 char *str;
2512 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002513 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302515 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 parms = str_parms_create_str(kvpairs);
2517
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302518 if (!parms)
2519 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002521 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002522
2523 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2524 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 val = atoi(value);
2526 /* no audio source uses val == 0 */
2527 if ((in->source != val) && (val != 0)) {
2528 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002529 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2530 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2531 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2532 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002533 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002534 err = voice_extn_compress_voip_open_input_stream(in);
2535 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002536 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002537 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002538 }
2539 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 }
2541 }
2542
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002543 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2544 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002546 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 in->device = val;
2548 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002549 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002550 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 }
2552 }
2553
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002554done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002556 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557
2558 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302559error:
Eric Laurent994a6932013-07-17 11:51:42 -07002560 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 return ret;
2562}
2563
2564static char* in_get_parameters(const struct audio_stream *stream,
2565 const char *keys)
2566{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002567 struct stream_in *in = (struct stream_in *)stream;
2568 struct str_parms *query = str_parms_create_str(keys);
2569 char *str;
2570 char value[256];
2571 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002572
2573 if (!query || !reply) {
2574 ALOGE("in_get_parameters: failed to create query or reply");
2575 return NULL;
2576 }
2577
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002578 ALOGV("%s: enter: keys - %s", __func__, keys);
2579
2580 voice_extn_in_get_parameters(in, query, reply);
2581
2582 str = str_parms_to_str(reply);
2583 str_parms_destroy(query);
2584 str_parms_destroy(reply);
2585
2586 ALOGV("%s: exit: returns - %s", __func__, str);
2587 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588}
2589
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002590static int in_set_gain(struct audio_stream_in *stream __unused,
2591 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592{
2593 return 0;
2594}
2595
2596static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2597 size_t bytes)
2598{
2599 struct stream_in *in = (struct stream_in *)stream;
2600 struct audio_device *adev = in->dev;
2601 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302602 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302605
2606 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302607 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302608 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302609 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302610 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002611 } else {
2612 if (in->is_st_session && !in->is_st_session_active) {
2613 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2614 ret= -EIO;;
2615 goto exit;
2616 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302617 }
2618 }
2619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002621 if (!in->is_st_session) {
2622 pthread_mutex_lock(&adev->lock);
2623 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2624 ret = voice_extn_compress_voip_start_input_stream(in);
2625 else
2626 ret = start_input_stream(in);
2627 pthread_mutex_unlock(&adev->lock);
2628 if (ret != 0) {
2629 goto exit;
2630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 }
2632 in->standby = 0;
2633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634
2635 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002636 if (audio_extn_ssr_get_enabled() &&
2637 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002638 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002639 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2640 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002641 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2642 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002643 else
2644 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302645 if (ret < 0)
2646 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 }
2648
2649 /*
2650 * Instead of writing zeroes here, we could trust the hardware
2651 * to always provide zeroes when muted.
2652 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302653 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2654 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 memset(buffer, 0, bytes);
2656
2657exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302658 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302659 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302660 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002661 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2662 session reading on LAB data. In this case do not set sound card state
2663 offline, instead mark this sound trigger session inactive to avoid
2664 further reading of LAB data from CPE driver. Marking the session
2665 inactive handles both CPE and ADSP SSR for sound trigger session */
2666 if (!in->is_st_session)
2667 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2668 else
2669 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 pthread_mutex_unlock(&in->lock);
2672
2673 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302674 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302675 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302676 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302677 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302678 in->standby = true;
2679 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302680 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002682 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002683 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302684 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
2686 return bytes;
2687}
2688
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002689static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690{
2691 return 0;
2692}
2693
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002694static int add_remove_audio_effect(const struct audio_stream *stream,
2695 effect_handle_t effect,
2696 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002698 struct stream_in *in = (struct stream_in *)stream;
2699 int status = 0;
2700 effect_descriptor_t desc;
2701
2702 status = (*effect)->get_descriptor(effect, &desc);
2703 if (status != 0)
2704 return status;
2705
2706 pthread_mutex_lock(&in->lock);
2707 pthread_mutex_lock(&in->dev->lock);
2708 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2709 in->enable_aec != enable &&
2710 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2711 in->enable_aec = enable;
2712 if (!in->standby)
2713 select_devices(in->dev, in->usecase);
2714 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002715 if (in->enable_ns != enable &&
2716 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2717 in->enable_ns = enable;
2718 if (!in->standby)
2719 select_devices(in->dev, in->usecase);
2720 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002721 pthread_mutex_unlock(&in->dev->lock);
2722 pthread_mutex_unlock(&in->lock);
2723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 return 0;
2725}
2726
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002727static int in_add_audio_effect(const struct audio_stream *stream,
2728 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
Eric Laurent994a6932013-07-17 11:51:42 -07002730 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002731 return add_remove_audio_effect(stream, effect, true);
2732}
2733
2734static int in_remove_audio_effect(const struct audio_stream *stream,
2735 effect_handle_t effect)
2736{
Eric Laurent994a6932013-07-17 11:51:42 -07002737 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002738 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739}
2740
2741static int adev_open_output_stream(struct audio_hw_device *dev,
2742 audio_io_handle_t handle,
2743 audio_devices_t devices,
2744 audio_output_flags_t flags,
2745 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002746 struct audio_stream_out **stream_out,
2747 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748{
2749 struct audio_device *adev = (struct audio_device *)dev;
2750 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002751 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002752 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302755
2756 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2757 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2758 ALOGE(" sound card is not active rejecting compress output open request");
2759 return -EINVAL;
2760 }
2761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2763
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302764 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2765 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2766 devices, flags, &out->stream);
2767
2768
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002769 if (!out) {
2770 return -ENOMEM;
2771 }
2772
Haynes Mathew George204045b2015-02-25 20:32:03 -08002773 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2774 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 if (devices == AUDIO_DEVICE_NONE)
2777 devices = AUDIO_DEVICE_OUT_SPEAKER;
2778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 out->flags = flags;
2780 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002781 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002782 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 out->sample_rate = config->sample_rate;
2784 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2785 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002786 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002787 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002788 out->non_blocking = 0;
2789 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790
2791 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002792 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2793 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002794 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2795 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2796
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002797 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002798 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2799 ret = read_hdmi_channel_masks(out);
2800
2801 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2802 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002803 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002804 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002805 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002806
2807 if (config->sample_rate == 0)
2808 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2809 if (config->channel_mask == 0)
2810 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2811
2812 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002813 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2815 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002817 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002819 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2820 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002821 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002822 ret = voice_extn_compress_voip_open_output_stream(out);
2823 if (ret != 0) {
2824 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2825 __func__, ret);
2826 goto error_open;
2827 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2829 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2830 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2831 ALOGE("%s: Unsupported Offload information", __func__);
2832 ret = -EINVAL;
2833 goto error_open;
2834 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002835
2836 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2837 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2838 ALOGV("read and update_pass through formats");
2839 ret = audio_extn_dolby_update_passt_formats(adev, out);
2840 if(ret != 0) {
2841 goto error_open;
2842 }
2843 if(config->offload_info.format == 0)
2844 config->offload_info.format = out->supported_formats[0];
2845 }
2846
Mingming Yin90310102013-11-13 16:57:00 -08002847 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002848 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 ALOGE("%s: Unsupported audio format", __func__);
2850 ret = -EINVAL;
2851 goto error_open;
2852 }
2853
2854 out->compr_config.codec = (struct snd_codec *)
2855 calloc(1, sizeof(struct snd_codec));
2856
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002857 if (!out->compr_config.codec) {
2858 ret = -ENOMEM;
2859 goto error_open;
2860 }
2861
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002862 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 if (config->offload_info.channel_mask)
2864 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002865 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002867 config->offload_info.channel_mask = config->channel_mask;
2868 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002869 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->sample_rate = config->offload_info.sample_rate;
2871
2872 out->stream.set_callback = out_set_callback;
2873 out->stream.pause = out_pause;
2874 out->stream.resume = out_resume;
2875 out->stream.drain = out_drain;
2876 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002877 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002879 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002880 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002881 audio_extn_dolby_get_snd_codec_id(adev, out,
2882 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002883 else
2884 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002886 if (audio_is_offload_pcm(config->offload_info.format)) {
2887 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002888 platform_get_pcm_offload_buffer_size(&config->offload_info);
2889 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2890 out->compr_config.fragment_size =
2891 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002892 } else {
2893 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002894 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002895 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2897 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302898 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 out->compr_config.codec->bit_rate =
2900 config->offload_info.bit_rate;
2901 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002902 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002904 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002905 /*TODO: Do we need to change it for passthrough */
2906 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002907
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2909 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002910 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2911 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002912 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002913 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2914
Mingming Yin3ee55c62014-08-04 14:23:35 -07002915 if (out->bit_width == 24) {
2916 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2917 }
2918
Amit Shekhar6f461b12014-08-01 14:52:58 -07002919 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002920 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002921
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2923 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002924
Alexy Josephaa54c872014-12-03 02:46:47 -08002925 if (config->offload_info.use_small_bufs) {
2926 //this flag is set from framework only if its for PCM formats
2927 //no need to check for PCM format again
2928 out->non_blocking = 0;
2929 out->use_small_bufs = true;
2930 ALOGI("Keep write blocking for small buff: non_blockling %d",
2931 out->non_blocking);
2932 }
2933
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002934 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002935 out->offload_state = OFFLOAD_STATE_IDLE;
2936 out->playback_started = 0;
2937
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002938 audio_extn_dts_create_state_notifier_node(out->usecase);
2939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 create_offload_callback_thread(out);
2941 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2942 __func__, config->offload_info.version,
2943 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002944 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002945 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002946 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2947 ret = voice_check_and_set_incall_music_usecase(adev, out);
2948 if (ret != 0) {
2949 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2950 __func__, ret);
2951 goto error_open;
2952 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002953 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2954 if (config->sample_rate == 0)
2955 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2956 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2957 config->sample_rate != 8000) {
2958 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2959 ret = -EINVAL;
2960 goto error_open;
2961 }
2962 out->sample_rate = config->sample_rate;
2963 out->config.rate = config->sample_rate;
2964 if (config->format == AUDIO_FORMAT_DEFAULT)
2965 config->format = AUDIO_FORMAT_PCM_16_BIT;
2966 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2967 config->format = AUDIO_FORMAT_PCM_16_BIT;
2968 ret = -EINVAL;
2969 goto error_open;
2970 }
2971 out->format = config->format;
2972 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2973 out->config = pcm_config_afe_proxy_playback;
2974 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002975 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002976 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2978 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002980 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2981 format = AUDIO_FORMAT_PCM_16_BIT;
2982 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2983 out->config = pcm_config_deep_buffer;
2984 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002985 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002986 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002987 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002988 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002989 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002990 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 }
2992
Amit Shekhar1d896042014-10-03 13:16:09 -07002993 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2994 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002995 /* TODO remove this hardcoding and check why width is zero*/
2996 if (out->bit_width == 0)
2997 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002998 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2999 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003000 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303001 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003002 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3003 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3004 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003005 if(adev->primary_output == NULL)
3006 adev->primary_output = out;
3007 else {
3008 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003009 ret = -EEXIST;
3010 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003011 }
3012 }
3013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 /* Check if this usecase is already existing */
3015 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003016 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3017 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003020 ret = -EEXIST;
3021 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 }
3023 pthread_mutex_unlock(&adev->lock);
3024
3025 out->stream.common.get_sample_rate = out_get_sample_rate;
3026 out->stream.common.set_sample_rate = out_set_sample_rate;
3027 out->stream.common.get_buffer_size = out_get_buffer_size;
3028 out->stream.common.get_channels = out_get_channels;
3029 out->stream.common.get_format = out_get_format;
3030 out->stream.common.set_format = out_set_format;
3031 out->stream.common.standby = out_standby;
3032 out->stream.common.dump = out_dump;
3033 out->stream.common.set_parameters = out_set_parameters;
3034 out->stream.common.get_parameters = out_get_parameters;
3035 out->stream.common.add_audio_effect = out_add_audio_effect;
3036 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3037 out->stream.get_latency = out_get_latency;
3038 out->stream.set_volume = out_set_volume;
3039 out->stream.write = out_write;
3040 out->stream.get_render_position = out_get_render_position;
3041 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003042 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003045 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003046 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
3048 config->format = out->stream.common.get_format(&out->stream.common);
3049 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3050 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3051
3052 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303053 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3054 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003055
3056 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3057 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3058 popcount(out->channel_mask), out->playback_started);
3059
Eric Laurent994a6932013-07-17 11:51:42 -07003060 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003062
3063error_open:
3064 free(out);
3065 *stream_out = NULL;
3066 ALOGD("%s: exit: ret %d", __func__, ret);
3067 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068}
3069
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003070static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 struct audio_stream_out *stream)
3072{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 struct stream_out *out = (struct stream_out *)stream;
3074 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003076
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303077 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3078
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303080 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003081 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303082 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003083 if(ret != 0)
3084 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3085 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003086 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 out_standby(&stream->common);
3088
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003089 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003090 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003092 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093 if (out->compr_config.codec != NULL)
3094 free(out->compr_config.codec);
3095 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003096
3097 if (adev->voice_tx_output == out)
3098 adev->voice_tx_output = NULL;
3099
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003100 pthread_cond_destroy(&out->cond);
3101 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003103 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104}
3105
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003106static void close_compress_sessions(struct audio_device *adev)
3107{
Mingming Yin7b762e72015-03-04 13:47:32 -08003108 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303109 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003110 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003111 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303112
3113 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003114 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303115 if (is_offload_usecase(usecase->id)) {
3116 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003117 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3118 out = usecase->stream.out;
3119 pthread_mutex_unlock(&adev->lock);
3120 out_standby(&out->stream.common);
3121 pthread_mutex_lock(&adev->lock);
3122 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303123 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003124 }
3125 pthread_mutex_unlock(&adev->lock);
3126}
3127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3129{
3130 struct audio_device *adev = (struct audio_device *)dev;
3131 struct str_parms *parms;
3132 char *str;
3133 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003134 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003135 int ret;
3136 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003138 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303141 if (!parms)
3142 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003143 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3144 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303146 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303147 struct listnode *node;
3148 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303149 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303150 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003151 //close compress sessions on OFFLINE status
3152 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303153 } else if (strstr(snd_card_status, "ONLINE")) {
3154 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303155 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303156 if (!platform_is_acdb_initialized(adev->platform)) {
3157 ret = platform_acdb_init(adev->platform);
3158 if(ret)
3159 ALOGE("acdb initialization is failed");
3160
3161 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303162 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303163 }
3164
3165 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003166 status = voice_set_parameters(adev, parms);
3167 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003168 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003170 status = platform_set_parameters(adev->platform, parms);
3171 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003172 goto done;
3173
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003174 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3175 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003176 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3178 adev->bluetooth_nrec = true;
3179 else
3180 adev->bluetooth_nrec = false;
3181 }
3182
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003183 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3184 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3186 adev->screen_off = false;
3187 else
3188 adev->screen_off = true;
3189 }
3190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003191 ret = str_parms_get_int(parms, "rotation", &val);
3192 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003193 bool reverse_speakers = false;
3194 switch(val) {
3195 // FIXME: note that the code below assumes that the speakers are in the correct placement
3196 // relative to the user when the device is rotated 90deg from its default rotation. This
3197 // assumption is device-specific, not platform-specific like this code.
3198 case 270:
3199 reverse_speakers = true;
3200 break;
3201 case 0:
3202 case 90:
3203 case 180:
3204 break;
3205 default:
3206 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003207 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003208 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003209 if (status == 0) {
3210 if (adev->speaker_lr_swap != reverse_speakers) {
3211 adev->speaker_lr_swap = reverse_speakers;
3212 // only update the selected device if there is active pcm playback
3213 struct audio_usecase *usecase;
3214 struct listnode *node;
3215 list_for_each(node, &adev->usecase_list) {
3216 usecase = node_to_item(node, struct audio_usecase, list);
3217 if (usecase->type == PCM_PLAYBACK) {
3218 select_devices(adev, usecase->id);
3219 break;
3220 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003221 }
3222 }
3223 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003224 }
3225
Mingming Yin514a8bc2014-07-29 15:22:21 -07003226 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3227 if (ret >= 0) {
3228 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3229 adev->bt_wb_speech_enabled = true;
3230 else
3231 adev->bt_wb_speech_enabled = false;
3232 }
3233
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003234 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3235 if (ret >= 0) {
3236 val = atoi(value);
3237 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3238 ALOGV("cache new edid");
3239 platform_cache_edid(adev->platform);
3240 }
3241 }
3242
3243 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3244 if (ret >= 0) {
3245 val = atoi(value);
3246 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3247 ALOGV("invalidate cached edid");
3248 platform_invalidate_edid(adev->platform);
3249 }
3250 }
3251
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003252 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003253
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003254done:
3255 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003256 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303257error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003258 ALOGV("%s: exit with code(%d)", __func__, status);
3259 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260}
3261
3262static char* adev_get_parameters(const struct audio_hw_device *dev,
3263 const char *keys)
3264{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003265 struct audio_device *adev = (struct audio_device *)dev;
3266 struct str_parms *reply = str_parms_create();
3267 struct str_parms *query = str_parms_create_str(keys);
3268 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303269 char value[256] = {0};
3270 int ret = 0;
3271
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003272 if (!query || !reply) {
3273 ALOGE("adev_get_parameters: failed to create query or reply");
3274 return NULL;
3275 }
3276
Naresh Tannirud7205b62014-06-20 02:54:48 +05303277 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3278 sizeof(value));
3279 if (ret >=0) {
3280 int val = 1;
3281 pthread_mutex_lock(&adev->snd_card_status.lock);
3282 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3283 val = 0;
3284 pthread_mutex_unlock(&adev->snd_card_status.lock);
3285 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3286 goto exit;
3287 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003288
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003289 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003290 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003291 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003292 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303293 pthread_mutex_unlock(&adev->lock);
3294
Naresh Tannirud7205b62014-06-20 02:54:48 +05303295exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003296 str = str_parms_to_str(reply);
3297 str_parms_destroy(query);
3298 str_parms_destroy(reply);
3299
3300 ALOGV("%s: exit: returns - %s", __func__, str);
3301 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302}
3303
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003304static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305{
3306 return 0;
3307}
3308
3309static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3310{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003311 int ret;
3312 struct audio_device *adev = (struct audio_device *)dev;
3313 pthread_mutex_lock(&adev->lock);
3314 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003315 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003316 pthread_mutex_unlock(&adev->lock);
3317 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318}
3319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003320static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3321 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return -ENOSYS;
3324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3327 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return -ENOSYS;
3330}
3331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003332static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3333 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334{
3335 return -ENOSYS;
3336}
3337
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003338static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3339 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340{
3341 return -ENOSYS;
3342}
3343
3344static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3345{
3346 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 pthread_mutex_lock(&adev->lock);
3349 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003350 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003352 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3353 voice_is_in_call(adev)) {
3354 voice_stop_call(adev);
3355 adev->current_call_output = NULL;
3356 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
3358 pthread_mutex_unlock(&adev->lock);
3359 return 0;
3360}
3361
3362static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3363{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003364 int ret;
3365
3366 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003367 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003368 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3369 pthread_mutex_unlock(&adev->lock);
3370
3371 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372}
3373
3374static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3375{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003376 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 return 0;
3378}
3379
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003380static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381 const struct audio_config *config)
3382{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003383 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003385 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3386 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387}
3388
3389static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003390 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 audio_devices_t devices,
3392 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003393 struct audio_stream_in **stream_in,
3394 audio_input_flags_t flags __unused,
3395 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003396 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397{
3398 struct audio_device *adev = (struct audio_device *)dev;
3399 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003400 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003401 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003402 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 *stream_in = NULL;
3405 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3406 return -EINVAL;
3407
3408 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003409
3410 if (!in) {
3411 ALOGE("failed to allocate input stream");
3412 return -ENOMEM;
3413 }
3414
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303415 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003416 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3417 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003419 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 in->stream.common.get_sample_rate = in_get_sample_rate;
3422 in->stream.common.set_sample_rate = in_set_sample_rate;
3423 in->stream.common.get_buffer_size = in_get_buffer_size;
3424 in->stream.common.get_channels = in_get_channels;
3425 in->stream.common.get_format = in_get_format;
3426 in->stream.common.set_format = in_set_format;
3427 in->stream.common.standby = in_standby;
3428 in->stream.common.dump = in_dump;
3429 in->stream.common.set_parameters = in_set_parameters;
3430 in->stream.common.get_parameters = in_get_parameters;
3431 in->stream.common.add_audio_effect = in_add_audio_effect;
3432 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3433 in->stream.set_gain = in_set_gain;
3434 in->stream.read = in_read;
3435 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3436
3437 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003438 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 in->standby = 1;
3441 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003442 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443
3444 /* Update config params with the requested sample rate and channels */
3445 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003446 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3447 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3448 is_low_latency = true;
3449#if LOW_LATENCY_CAPTURE_USE_CASE
3450 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3451#endif
3452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003455 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003457 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303458 if (adev->mode != AUDIO_MODE_IN_CALL) {
3459 ret = -EINVAL;
3460 goto err_open;
3461 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003462 if (config->sample_rate == 0)
3463 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3464 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3465 config->sample_rate != 8000) {
3466 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3467 ret = -EINVAL;
3468 goto err_open;
3469 }
3470 if (config->format == AUDIO_FORMAT_DEFAULT)
3471 config->format = AUDIO_FORMAT_PCM_16_BIT;
3472 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3473 config->format = AUDIO_FORMAT_PCM_16_BIT;
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477
3478 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3479 in->config = pcm_config_afe_proxy_record;
3480 in->config.channels = channel_count;
3481 in->config.rate = config->sample_rate;
3482 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003483 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003484 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003485 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3486 ret = -EINVAL;
3487 goto err_open;
3488 }
3489 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003490 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003491 }
Mingming Yine62d7842013-10-25 16:26:03 -07003492 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003493 audio_extn_compr_cap_format_supported(config->format) &&
3494 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003495 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003496 } else {
3497 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003498 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003499 buffer_size = get_input_buffer_size(config->sample_rate,
3500 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003501 channel_count,
3502 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003503 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003504 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3505 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3506 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3507 (in->config.rate == 8000 || in->config.rate == 16000) &&
3508 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3509 voice_extn_compress_voip_open_input_stream(in);
3510 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003513 /* This stream could be for sound trigger lab,
3514 get sound trigger pcm if present */
3515 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303516 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003519 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003520 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521
3522err_open:
3523 free(in);
3524 *stream_in = NULL;
3525 return ret;
3526}
3527
3528static void adev_close_input_stream(struct audio_hw_device *dev,
3529 struct audio_stream_in *stream)
3530{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003531 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003532 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003533 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303534
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303535 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003536
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303537 /* Disable echo reference while closing input stream */
3538 platform_set_echo_reference(adev->platform, false);
3539
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303541 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003542 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303543 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003544 if (ret != 0)
3545 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3546 __func__, ret);
3547 } else
3548 in_standby(&stream->common);
3549
Mingming Yin7b762e72015-03-04 13:47:32 -08003550 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003551 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003552 audio_extn_ssr_deinit();
3553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554
Mingming Yine62d7842013-10-25 16:26:03 -07003555 if(audio_extn_compr_cap_enabled() &&
3556 audio_extn_compr_cap_format_supported(in->config.format))
3557 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003558
3559 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 return;
3561}
3562
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003563static int adev_dump(const audio_hw_device_t *device __unused,
3564 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565{
3566 return 0;
3567}
3568
3569static int adev_close(hw_device_t *device)
3570{
3571 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003572
3573 if (!adev)
3574 return 0;
3575
3576 pthread_mutex_lock(&adev_init_lock);
3577
3578 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003579 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003580 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003581 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003582 audio_route_free(adev->audio_route);
3583 free(adev->snd_dev_ref_cnt);
3584 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003585 free(device);
3586 adev = NULL;
3587 }
3588 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 return 0;
3590}
3591
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003592/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3593 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3594 * just that it _might_ work.
3595 */
3596static int period_size_is_plausible_for_low_latency(int period_size)
3597{
3598 switch (period_size) {
3599 case 160:
3600 case 240:
3601 case 320:
3602 case 480:
3603 return 1;
3604 default:
3605 return 0;
3606 }
3607}
3608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609static int adev_open(const hw_module_t *module, const char *name,
3610 hw_device_t **device)
3611{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003612 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003614 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3616
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003617 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003618 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003619 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003620 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003621 ALOGD("%s: returning existing instance of adev", __func__);
3622 ALOGD("%s: exit", __func__);
3623 pthread_mutex_unlock(&adev_init_lock);
3624 return 0;
3625 }
3626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 adev = calloc(1, sizeof(struct audio_device));
3628
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003629 if (!adev) {
3630 pthread_mutex_unlock(&adev_init_lock);
3631 return -ENOMEM;
3632 }
3633
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003634 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3637 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3638 adev->device.common.module = (struct hw_module_t *)module;
3639 adev->device.common.close = adev_close;
3640
3641 adev->device.init_check = adev_init_check;
3642 adev->device.set_voice_volume = adev_set_voice_volume;
3643 adev->device.set_master_volume = adev_set_master_volume;
3644 adev->device.get_master_volume = adev_get_master_volume;
3645 adev->device.set_master_mute = adev_set_master_mute;
3646 adev->device.get_master_mute = adev_get_master_mute;
3647 adev->device.set_mode = adev_set_mode;
3648 adev->device.set_mic_mute = adev_set_mic_mute;
3649 adev->device.get_mic_mute = adev_get_mic_mute;
3650 adev->device.set_parameters = adev_set_parameters;
3651 adev->device.get_parameters = adev_get_parameters;
3652 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3653 adev->device.open_output_stream = adev_open_output_stream;
3654 adev->device.close_output_stream = adev_close_output_stream;
3655 adev->device.open_input_stream = adev_open_input_stream;
3656 adev->device.close_input_stream = adev_close_input_stream;
3657 adev->device.dump = adev_dump;
3658
3659 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003661 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003662 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003665 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003666 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003667 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003668 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003669 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003670 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003671 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303672
3673 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3674 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003676 adev->platform = platform_init(adev);
3677 if (!adev->platform) {
3678 free(adev->snd_dev_ref_cnt);
3679 free(adev);
3680 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3681 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003682 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003683 return -EINVAL;
3684 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003685
Naresh Tanniru4c630392014-05-12 01:05:52 +05303686 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3687
Eric Laurentc4aef752013-09-12 17:45:53 -07003688 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3689 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3690 if (adev->visualizer_lib == NULL) {
3691 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3692 } else {
3693 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3694 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003695 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003696 "visualizer_hal_start_output");
3697 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003698 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003699 "visualizer_hal_stop_output");
3700 }
3701 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003702 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003703 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003704
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003705 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3706 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3707 if (adev->offload_effects_lib == NULL) {
3708 ALOGE("%s: DLOPEN failed for %s", __func__,
3709 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3710 } else {
3711 ALOGV("%s: DLOPEN successful for %s", __func__,
3712 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3713 adev->offload_effects_start_output =
3714 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3715 "offload_effects_bundle_hal_start_output");
3716 adev->offload_effects_stop_output =
3717 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3718 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003719 adev->offload_effects_set_hpx_state =
3720 (int (*)(bool))dlsym(adev->offload_effects_lib,
3721 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003722 }
3723 }
3724
Mingming Yin514a8bc2014-07-29 15:22:21 -07003725 adev->bt_wb_speech_enabled = false;
3726
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003727 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 *device = &adev->device.common;
3729
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003730 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3731 &adev->streams_output_cfg_list);
3732
Kiran Kandi910e1862013-10-29 13:29:42 -07003733 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003734
3735 char value[PROPERTY_VALUE_MAX];
3736 int trial;
3737 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3738 trial = atoi(value);
3739 if (period_size_is_plausible_for_low_latency(trial)) {
3740 pcm_config_low_latency.period_size = trial;
3741 pcm_config_low_latency.start_threshold = trial / 4;
3742 pcm_config_low_latency.avail_min = trial / 4;
3743 configured_low_latency_capture_period_size = trial;
3744 }
3745 }
3746 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3747 trial = atoi(value);
3748 if (period_size_is_plausible_for_low_latency(trial)) {
3749 configured_low_latency_capture_period_size = trial;
3750 }
3751 }
3752
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003753 pthread_mutex_unlock(&adev_init_lock);
3754
Eric Laurent994a6932013-07-17 11:51:42 -07003755 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 return 0;
3757}
3758
3759static struct hw_module_methods_t hal_module_methods = {
3760 .open = adev_open,
3761};
3762
3763struct audio_module HAL_MODULE_INFO_SYM = {
3764 .common = {
3765 .tag = HARDWARE_MODULE_TAG,
3766 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3767 .hal_api_version = HARDWARE_HAL_API_VERSION,
3768 .id = AUDIO_HARDWARE_MODULE_ID,
3769 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003770 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 .methods = &hal_module_methods,
3772 },
3773};