blob: 138bd3c14ee4047aa12fd72793c63620c51f0a1a [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 ||
291 format == AUDIO_FORMAT_WMA ||
292 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800293 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700294
295 return false;
296}
297
298static int get_snd_codec_id(audio_format_t format)
299{
300 int id = 0;
301
Ashish Jainf9b78162014-08-25 20:36:25 +0530302 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700303 case AUDIO_FORMAT_MP3:
304 id = SND_AUDIOCODEC_MP3;
305 break;
306 case AUDIO_FORMAT_AAC:
307 id = SND_AUDIOCODEC_AAC;
308 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530309 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800310 id = SND_AUDIOCODEC_PCM;
311 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700312 case AUDIO_FORMAT_FLAC:
313 id = SND_AUDIOCODEC_FLAC;
314 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800315 case AUDIO_FORMAT_WMA:
316 id = SND_AUDIOCODEC_WMA;
317 break;
318 case AUDIO_FORMAT_WMA_PRO:
319 id = SND_AUDIOCODEC_WMA_PRO;
320 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700321 default:
Mingming Yin90310102013-11-13 16:57:00 -0800322 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700323 }
324
325 return id;
326}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800327
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530328int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530329{
330 int snd_scard_state;
331
332 if (!adev)
333 return SND_CARD_STATE_OFFLINE;
334
335 pthread_mutex_lock(&adev->snd_card_status.lock);
336 snd_scard_state = adev->snd_card_status.state;
337 pthread_mutex_unlock(&adev->snd_card_status.lock);
338
339 return snd_scard_state;
340}
341
342static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
343{
344 if (!adev)
345 return -ENOSYS;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 adev->snd_card_status.state = snd_scard_state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return 0;
352}
353
Avinash Vaish71a8b972014-07-24 15:36:33 +0530354static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
355 struct audio_usecase *uc_info)
356{
357 struct listnode *node;
358 struct audio_usecase *usecase;
359
360 if (uc_info == NULL)
361 return -EINVAL;
362
363 /* Re-route all voice usecases on the shared backend other than the
364 specified usecase to new snd devices */
365 list_for_each(node, &adev->usecase_list) {
366 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800367 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530368 enable_audio_route(adev, usecase);
369 }
370 return 0;
371}
372
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700373int pcm_ioctl(struct pcm *pcm, int request, ...)
374{
375 va_list ap;
376 void * arg;
377 int pcm_fd = *(int*)pcm;
378
379 va_start(ap, request);
380 arg = va_arg(ap, void *);
381 va_end(ap);
382
383 return ioctl(pcm_fd, request, arg);
384}
385
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700386int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700387 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800388{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700389 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700390 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800391
392 if (usecase == NULL)
393 return -EINVAL;
394
395 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
396
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800397 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700398 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800399 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700400 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800401
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800402#ifdef DS1_DOLBY_DAP_ENABLED
403 audio_extn_dolby_set_dmid(adev);
404 audio_extn_dolby_set_endpoint(adev);
405#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700406 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700407 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530408 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700409 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700410 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700412 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700413 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
414 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800415 ALOGV("%s: exit", __func__);
416 return 0;
417}
418
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700419int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700420 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800421{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700422 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700423 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800424
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530425 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800426 return -EINVAL;
427
428 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700429 if (usecase->type == PCM_CAPTURE)
430 snd_device = usecase->in_snd_device;
431 else
432 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800433 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700434 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700435 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
436 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700437 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530438 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439 ALOGV("%s: exit", __func__);
440 return 0;
441}
442
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700443int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700444 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800445{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700446 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
447
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800448 if (snd_device < SND_DEVICE_MIN ||
449 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800450 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800451 return -EINVAL;
452 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700453
454 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700455
456 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
457 ALOGE("%s: Invalid sound device returned", __func__);
458 return -EINVAL;
459 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700460 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700461 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700462 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700463 return 0;
464 }
465
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700466 if (audio_extn_spkr_prot_is_enabled())
467 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700468 /* start usb playback thread */
469 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
470 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
471 audio_extn_usb_start_playback(adev);
472
473 /* start usb capture thread */
474 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
475 audio_extn_usb_start_capture(adev);
476
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800477 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
478 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700479 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700480 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
481 adev->snd_dev_ref_cnt[snd_device]--;
482 return -EINVAL;
483 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200484 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800485 if (audio_extn_spkr_prot_start_processing(snd_device)) {
486 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200487 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800488 return -EINVAL;
489 }
490 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 ALOGV("%s: snd_device(%d: %s)", __func__,
492 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700493 /* due to the possibility of calibration overwrite between listen
494 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700495 audio_extn_sound_trigger_update_device_status(snd_device,
496 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530497 audio_extn_listen_update_device_status(snd_device,
498 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700499 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700500 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700501 audio_extn_sound_trigger_update_device_status(snd_device,
502 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530503 audio_extn_listen_update_device_status(snd_device,
504 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700505 return -EINVAL;
506 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300507 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700508 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800510 return 0;
511}
512
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700514 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800515{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700516 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
517
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800518 if (snd_device < SND_DEVICE_MIN ||
519 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800520 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800521 return -EINVAL;
522 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700523 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
524 ALOGE("%s: device ref cnt is already 0", __func__);
525 return -EINVAL;
526 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700527
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700528 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700529
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700530 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
531 ALOGE("%s: Invalid sound device returned", __func__);
532 return -EINVAL;
533 }
534
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700536 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700537 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800538 /* exit usb play back thread */
539 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
540 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
541 audio_extn_usb_stop_playback();
542
543 /* exit usb capture thread */
544 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700545 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800546
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800547 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
548 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700549 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700550 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300551 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700552 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300553 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700554
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200555 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700556 audio_extn_sound_trigger_update_device_status(snd_device,
557 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530558 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800559 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700560 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562 return 0;
563}
564
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565static void check_usecases_codec_backend(struct audio_device *adev,
566 struct audio_usecase *uc_info,
567 snd_device_t snd_device)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571 bool switch_device[AUDIO_USECASE_MAX];
572 int i, num_uc_to_switch = 0;
573
574 /*
575 * This function is to make sure that all the usecases that are active on
576 * the hardware codec backend are always routed to any one device that is
577 * handled by the hardware codec.
578 * For example, if low-latency and deep-buffer usecases are currently active
579 * on speaker and out_set_parameters(headset) is received on low-latency
580 * output, then we have to make sure deep-buffer is also switched to headset,
581 * because of the limitation that both the devices cannot be enabled
582 * at the same time as they share the same backend.
583 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700584 /*
585 * This call is to check if we need to force routing for a particular stream
586 * If there is a backend configuration change for the device when a
587 * new stream starts, then ADM needs to be closed and re-opened with the new
588 * configuraion. This call check if we need to re-route all the streams
589 * associated with the backend. Touch tone + 24 bit playback.
590 */
591 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
592
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 /* Disable all the usecases on the shared backend other than the
594 specified usecase */
595 for (i = 0; i < AUDIO_USECASE_MAX; i++)
596 switch_device[i] = false;
597
598 list_for_each(node, &adev->usecase_list) {
599 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800600 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700602 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
604 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
605 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700606 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700607 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 switch_device[usecase->id] = true;
609 num_uc_to_switch++;
610 }
611 }
612
613 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700614 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530616 /* Make sure the previous devices to be disabled first and then enable the
617 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 list_for_each(node, &adev->usecase_list) {
619 usecase = node_to_item(node, struct audio_usecase, list);
620 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700621 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 }
623 }
624
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700625 list_for_each(node, &adev->usecase_list) {
626 usecase = node_to_item(node, struct audio_usecase, list);
627 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700628 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700629 }
630 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700632 /* Re-route all the usecases on the shared backend other than the
633 specified usecase to new snd devices */
634 list_for_each(node, &adev->usecase_list) {
635 usecase = node_to_item(node, struct audio_usecase, list);
636 /* Update the out_snd_device only before enabling the audio route */
637 if (switch_device[usecase->id] ) {
638 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800639 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530640 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700641 }
642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 }
644}
645
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700646static void check_and_route_capture_usecases(struct audio_device *adev,
647 struct audio_usecase *uc_info,
648 snd_device_t snd_device)
649{
650 struct listnode *node;
651 struct audio_usecase *usecase;
652 bool switch_device[AUDIO_USECASE_MAX];
653 int i, num_uc_to_switch = 0;
654
655 /*
656 * This function is to make sure that all the active capture usecases
657 * are always routed to the same input sound device.
658 * For example, if audio-record and voice-call usecases are currently
659 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
660 * is received for voice call then we have to make sure that audio-record
661 * usecase is also switched to earpiece i.e. voice-dmic-ef,
662 * because of the limitation that two devices cannot be enabled
663 * at the same time if they share the same backend.
664 */
665 for (i = 0; i < AUDIO_USECASE_MAX; i++)
666 switch_device[i] = false;
667
668 list_for_each(node, &adev->usecase_list) {
669 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800670 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700671 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700672 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530673 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700674 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700675 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
676 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700677 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700678 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700679 switch_device[usecase->id] = true;
680 num_uc_to_switch++;
681 }
682 }
683
684 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700685 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700686
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530687 /* Make sure the previous devices to be disabled first and then enable the
688 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700689 list_for_each(node, &adev->usecase_list) {
690 usecase = node_to_item(node, struct audio_usecase, list);
691 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700692 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800693 }
694 }
695
696 list_for_each(node, &adev->usecase_list) {
697 usecase = node_to_item(node, struct audio_usecase, list);
698 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700699 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700700 }
701 }
702
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 /* Re-route all the usecases on the shared backend other than the
704 specified usecase to new snd devices */
705 list_for_each(node, &adev->usecase_list) {
706 usecase = node_to_item(node, struct audio_usecase, list);
707 /* Update the in_snd_device only before enabling the audio route */
708 if (switch_device[usecase->id] ) {
709 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800710 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530711 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700712 }
713 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714 }
715}
716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800717/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700718static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800719{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700720 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700721 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722
723 switch (channels) {
724 /*
725 * Do not handle stereo output in Multi-channel cases
726 * Stereo case is handled in normal playback path
727 */
728 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700729 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
730 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
731 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
732 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
733 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
734 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800735 break;
736 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700737 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
738 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
739 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
740 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
741 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
742 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
743 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744 break;
745 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700746 ALOGE("HDMI does not support multi channel playback");
747 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800748 break;
749 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700750 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751}
752
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800753audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
754 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700755{
756 struct audio_usecase *usecase;
757 struct listnode *node;
758
759 list_for_each(node, &adev->usecase_list) {
760 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800761 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700762 ALOGV("%s: usecase id %d", __func__, usecase->id);
763 return usecase->id;
764 }
765 }
766 return USECASE_INVALID;
767}
768
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700769struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700770 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700771{
772 struct audio_usecase *usecase;
773 struct listnode *node;
774
775 list_for_each(node, &adev->usecase_list) {
776 usecase = node_to_item(node, struct audio_usecase, list);
777 if (usecase->id == uc_id)
778 return usecase;
779 }
780 return NULL;
781}
782
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700783int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800785 snd_device_t out_snd_device = SND_DEVICE_NONE;
786 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 struct audio_usecase *usecase = NULL;
788 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800789 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800790 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800791 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800792 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700793 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800794
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795 usecase = get_usecase_from_list(adev, uc_id);
796 if (usecase == NULL) {
797 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
798 return -EINVAL;
799 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800800
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800801 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800802 (usecase->type == VOIP_CALL) ||
803 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700804 out_snd_device = platform_get_output_snd_device(adev->platform,
805 usecase->stream.out->devices);
806 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700807 usecase->devices = usecase->stream.out->devices;
808 } else {
809 /*
810 * If the voice call is active, use the sound devices of voice call usecase
811 * so that it would not result any device switch. All the usecases will
812 * be switched to new device when select_devices() is called for voice call
813 * usecase. This is to avoid switching devices for voice call when
814 * check_usecases_codec_backend() is called below.
815 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700816 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700817 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800818 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700819 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
820 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821 in_snd_device = vc_usecase->in_snd_device;
822 out_snd_device = vc_usecase->out_snd_device;
823 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800824 } else if (voice_extn_compress_voip_is_active(adev)) {
825 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700826 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530827 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700828 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800829 in_snd_device = voip_usecase->in_snd_device;
830 out_snd_device = voip_usecase->out_snd_device;
831 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800832 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800833 hfp_ucid = audio_extn_hfp_get_usecase();
834 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700835 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800836 in_snd_device = hfp_usecase->in_snd_device;
837 out_snd_device = hfp_usecase->out_snd_device;
838 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 }
840 if (usecase->type == PCM_PLAYBACK) {
841 usecase->devices = usecase->stream.out->devices;
842 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700843 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700844 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700846 if (usecase->stream.out == adev->primary_output &&
847 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800848 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
849 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700850 select_devices(adev, adev->active_input->usecase);
851 }
852 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 } else if (usecase->type == PCM_CAPTURE) {
854 usecase->devices = usecase->stream.in->device;
855 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700856 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700857 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530858 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
859 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
860 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
861 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700862 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800863 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700864 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
865 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700866 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700867 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 }
870 }
871
872 if (out_snd_device == usecase->out_snd_device &&
873 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800874 return 0;
875 }
876
sangwoobc677242013-08-08 16:53:43 +0900877 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700878 out_snd_device, platform_get_snd_device_name(out_snd_device),
879 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 /*
882 * Limitation: While in call, to do a device switch we need to disable
883 * and enable both RX and TX devices though one of them is same as current
884 * device.
885 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700886 if ((usecase->type == VOICE_CALL) &&
887 (usecase->in_snd_device != SND_DEVICE_NONE) &&
888 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700889 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800890 }
891
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 /* Disable current sound devices */
893 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700894 disable_audio_route(adev, usecase);
895 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800896 }
897
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700899 disable_audio_route(adev, usecase);
900 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800901 }
902
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800903 /* Applicable only on the targets that has external modem.
904 * New device information should be sent to modem before enabling
905 * the devices to reduce in-call device switch time.
906 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700907 if ((usecase->type == VOICE_CALL) &&
908 (usecase->in_snd_device != SND_DEVICE_NONE) &&
909 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800910 status = platform_switch_voice_call_enable_device_config(adev->platform,
911 out_snd_device,
912 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700913 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800914
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 /* Enable new sound devices */
916 if (out_snd_device != SND_DEVICE_NONE) {
917 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
918 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700919 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920 }
921
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922 if (in_snd_device != SND_DEVICE_NONE) {
923 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700924 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700925 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926
Avinash Vaish71a8b972014-07-24 15:36:33 +0530927 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700928 status = platform_switch_voice_call_device_post(adev->platform,
929 out_snd_device,
930 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530931 enable_audio_route_for_voice_usecases(adev, usecase);
932 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800933
sangwoo170731f2013-06-08 15:36:36 +0900934 usecase->in_snd_device = in_snd_device;
935 usecase->out_snd_device = out_snd_device;
936
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530937 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700938 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530939 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700940 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530941 usecase->stream.out->flags,
942 usecase->stream.out->format,
943 usecase->stream.out->sample_rate,
944 usecase->stream.out->bit_width,
945 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700946 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530947 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700948
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900950
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800951 /* Applicable only on the targets that has external modem.
952 * Enable device command should be sent to modem only after
953 * enabling voice call mixer controls
954 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700955 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800956 status = platform_switch_voice_call_usecase_route_post(adev->platform,
957 out_snd_device,
958 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530959 ALOGD("%s: done",__func__);
960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961 return status;
962}
963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964static int stop_input_stream(struct stream_in *in)
965{
966 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800967 struct audio_usecase *uc_info;
968 struct audio_device *adev = in->dev;
969
Eric Laurentc8400632013-02-14 19:04:54 -0800970 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971
Eric Laurent994a6932013-07-17 11:51:42 -0700972 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700973 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974 uc_info = get_usecase_from_list(adev, in->usecase);
975 if (uc_info == NULL) {
976 ALOGE("%s: Could not find the usecase (%d) in the list",
977 __func__, in->usecase);
978 return -EINVAL;
979 }
980
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800981 /* Close in-call recording streams */
982 voice_check_and_stop_incall_rec_usecase(adev, in);
983
Eric Laurent150dbfe2013-02-27 14:31:02 -0800984 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700985 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986
987 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700988 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800990 list_remove(&uc_info->list);
991 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992
Eric Laurent994a6932013-07-17 11:51:42 -0700993 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 return ret;
995}
996
997int start_input_stream(struct stream_in *in)
998{
999 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001000 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001 struct audio_usecase *uc_info;
1002 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301003 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004
Mingming Yine62d7842013-10-25 16:26:03 -07001005 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301006 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1007 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001008
Naresh Tanniru80659832014-06-04 18:17:56 +05301009
1010 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301011 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301012 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301013 goto error_config;
1014 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301015
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001016 /* Check if source matches incall recording usecase criteria */
1017 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1018 if (ret)
1019 goto error_config;
1020 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001021 ALOGD("%s: Updated usecase(%d: %s)",
1022 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001023
Eric Laurentb23d5282013-05-14 15:27:20 -07001024 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 if (in->pcm_device_id < 0) {
1026 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1027 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001028 ret = -EINVAL;
1029 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031
1032 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001034
1035 if (!uc_info) {
1036 ret = -ENOMEM;
1037 goto error_config;
1038 }
1039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040 uc_info->id = in->usecase;
1041 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001042 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043 uc_info->devices = in->device;
1044 uc_info->in_snd_device = SND_DEVICE_NONE;
1045 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001047 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301048 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050
Eric Laurentc8400632013-02-14 19:04:54 -08001051 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001052 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1053
1054 unsigned int flags = PCM_IN;
1055 unsigned int pcm_open_retry_count = 0;
1056
1057 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1058 flags |= PCM_MMAP | PCM_NOIRQ;
1059 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1060 }
1061
1062 while (1) {
1063 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1064 flags, &in->config);
1065 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1066 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1067 if (in->pcm != NULL) {
1068 pcm_close(in->pcm);
1069 in->pcm = NULL;
1070 }
1071 if (pcm_open_retry_count-- == 0) {
1072 ret = -EIO;
1073 goto error_open;
1074 }
1075 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1076 continue;
1077 }
1078 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301080 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301081
Eric Laurent994a6932013-07-17 11:51:42 -07001082 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001083 return ret;
1084
1085error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301087 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001088
1089error_config:
1090 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001092
1093 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094}
1095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001096/* must be called with out->lock locked */
1097static int send_offload_cmd_l(struct stream_out* out, int command)
1098{
1099 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1100
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001101 if (!cmd) {
1102 ALOGE("failed to allocate mem for command 0x%x", command);
1103 return -ENOMEM;
1104 }
1105
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001106 ALOGVV("%s %d", __func__, command);
1107
1108 cmd->cmd = command;
1109 list_add_tail(&out->offload_cmd_list, &cmd->node);
1110 pthread_cond_signal(&out->offload_cond);
1111 return 0;
1112}
1113
1114/* must be called iwth out->lock locked */
1115static void stop_compressed_output_l(struct stream_out *out)
1116{
1117 out->offload_state = OFFLOAD_STATE_IDLE;
1118 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001119 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001120 if (out->compr != NULL) {
1121 compress_stop(out->compr);
1122 while (out->offload_thread_blocked) {
1123 pthread_cond_wait(&out->cond, &out->lock);
1124 }
1125 }
1126}
1127
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001128bool is_offload_usecase(audio_usecase_t uc_id)
1129{
1130 unsigned int i;
1131 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1132 if (uc_id == offload_usecases[i])
1133 return true;
1134 }
1135 return false;
1136}
1137
1138static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1139{
1140 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1141 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1142 char value[PROPERTY_VALUE_MAX] = {0};
1143
1144 property_get("audio.offload.multiple.enabled", value, NULL);
1145 if (!(atoi(value) || !strncmp("true", value, 4)))
1146 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1147
1148 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1149 for (i = 0; i < num_usecase; i++) {
1150 if (!(adev->offload_usecases_state & (0x1<<i))) {
1151 adev->offload_usecases_state |= 0x1 << i;
1152 ret = offload_usecases[i];
1153 break;
1154 }
1155 }
1156 ALOGV("%s: offload usecase is %d", __func__, ret);
1157 return ret;
1158}
1159
1160static void free_offload_usecase(struct audio_device *adev,
1161 audio_usecase_t uc_id)
1162{
1163 unsigned int i;
1164 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1165 if (offload_usecases[i] == uc_id) {
1166 adev->offload_usecases_state &= ~(0x1<<i);
1167 break;
1168 }
1169 }
1170 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1171}
1172
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001173static void *offload_thread_loop(void *context)
1174{
1175 struct stream_out *out = (struct stream_out *) context;
1176 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001177 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001178
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001179 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1180 set_sched_policy(0, SP_FOREGROUND);
1181 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1182
1183 ALOGV("%s", __func__);
1184 pthread_mutex_lock(&out->lock);
1185 for (;;) {
1186 struct offload_cmd *cmd = NULL;
1187 stream_callback_event_t event;
1188 bool send_callback = false;
1189
1190 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1191 __func__, list_empty(&out->offload_cmd_list),
1192 out->offload_state);
1193 if (list_empty(&out->offload_cmd_list)) {
1194 ALOGV("%s SLEEPING", __func__);
1195 pthread_cond_wait(&out->offload_cond, &out->lock);
1196 ALOGV("%s RUNNING", __func__);
1197 continue;
1198 }
1199
1200 item = list_head(&out->offload_cmd_list);
1201 cmd = node_to_item(item, struct offload_cmd, node);
1202 list_remove(item);
1203
1204 ALOGVV("%s STATE %d CMD %d out->compr %p",
1205 __func__, out->offload_state, cmd->cmd, out->compr);
1206
1207 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1208 free(cmd);
1209 break;
1210 }
1211
1212 if (out->compr == NULL) {
1213 ALOGE("%s: Compress handle is NULL", __func__);
1214 pthread_cond_signal(&out->cond);
1215 continue;
1216 }
1217 out->offload_thread_blocked = true;
1218 pthread_mutex_unlock(&out->lock);
1219 send_callback = false;
1220 switch(cmd->cmd) {
1221 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001222 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001223 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001224 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001225 send_callback = true;
1226 event = STREAM_CBK_EVENT_WRITE_READY;
1227 break;
1228 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001229 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301230 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001231 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301232 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001233 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301234 if (ret < 0)
1235 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301236 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301237 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001238 compress_drain(out->compr);
1239 else
1240 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301241 if (ret != -ENETRESET) {
1242 send_callback = true;
1243 event = STREAM_CBK_EVENT_DRAIN_READY;
1244 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1245 } else
1246 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001247 break;
1248 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001249 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001250 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001251 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001252 send_callback = true;
1253 event = STREAM_CBK_EVENT_DRAIN_READY;
1254 break;
1255 default:
1256 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1257 break;
1258 }
1259 pthread_mutex_lock(&out->lock);
1260 out->offload_thread_blocked = false;
1261 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001262 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001263 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001264 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001265 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001266 free(cmd);
1267 }
1268
1269 pthread_cond_signal(&out->cond);
1270 while (!list_empty(&out->offload_cmd_list)) {
1271 item = list_head(&out->offload_cmd_list);
1272 list_remove(item);
1273 free(node_to_item(item, struct offload_cmd, node));
1274 }
1275 pthread_mutex_unlock(&out->lock);
1276
1277 return NULL;
1278}
1279
1280static int create_offload_callback_thread(struct stream_out *out)
1281{
1282 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1283 list_init(&out->offload_cmd_list);
1284 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1285 offload_thread_loop, out);
1286 return 0;
1287}
1288
1289static int destroy_offload_callback_thread(struct stream_out *out)
1290{
1291 pthread_mutex_lock(&out->lock);
1292 stop_compressed_output_l(out);
1293 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1294
1295 pthread_mutex_unlock(&out->lock);
1296 pthread_join(out->offload_thread, (void **) NULL);
1297 pthread_cond_destroy(&out->offload_cond);
1298
1299 return 0;
1300}
1301
Eric Laurent07eeafd2013-10-06 12:52:49 -07001302static bool allow_hdmi_channel_config(struct audio_device *adev)
1303{
1304 struct listnode *node;
1305 struct audio_usecase *usecase;
1306 bool ret = true;
1307
1308 list_for_each(node, &adev->usecase_list) {
1309 usecase = node_to_item(node, struct audio_usecase, list);
1310 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1311 /*
1312 * If voice call is already existing, do not proceed further to avoid
1313 * disabling/enabling both RX and TX devices, CSD calls, etc.
1314 * Once the voice call done, the HDMI channels can be configured to
1315 * max channels of remaining use cases.
1316 */
1317 if (usecase->id == USECASE_VOICE_CALL) {
1318 ALOGD("%s: voice call is active, no change in HDMI channels",
1319 __func__);
1320 ret = false;
1321 break;
1322 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1323 ALOGD("%s: multi channel playback is active, "
1324 "no change in HDMI channels", __func__);
1325 ret = false;
1326 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001327 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001328 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001329 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1330 ", no change in HDMI channels", __func__,
1331 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001332 ret = false;
1333 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001334 }
1335 }
1336 }
1337 return ret;
1338}
1339
1340static int check_and_set_hdmi_channels(struct audio_device *adev,
1341 unsigned int channels)
1342{
1343 struct listnode *node;
1344 struct audio_usecase *usecase;
1345
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001346 unsigned int supported_channels = platform_edid_get_max_channels(
1347 adev->platform);
1348 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001349 /* Check if change in HDMI channel config is allowed */
1350 if (!allow_hdmi_channel_config(adev))
1351 return 0;
1352
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001353 if (channels > supported_channels)
1354 channels = supported_channels;
1355
Eric Laurent07eeafd2013-10-06 12:52:49 -07001356 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001357 ALOGD("%s: Requested channels are same as current channels(%d)",
1358 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001359 return 0;
1360 }
1361
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001362 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001363 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001364 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001365 adev->cur_hdmi_channels = channels;
1366
1367 /*
1368 * Deroute all the playback streams routed to HDMI so that
1369 * the back end is deactivated. Note that backend will not
1370 * be deactivated if any one stream is connected to it.
1371 */
1372 list_for_each(node, &adev->usecase_list) {
1373 usecase = node_to_item(node, struct audio_usecase, list);
1374 if (usecase->type == PCM_PLAYBACK &&
1375 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001376 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001377 }
1378 }
1379
1380 /*
1381 * Enable all the streams disabled above. Now the HDMI backend
1382 * will be activated with new channel configuration
1383 */
1384 list_for_each(node, &adev->usecase_list) {
1385 usecase = node_to_item(node, struct audio_usecase, list);
1386 if (usecase->type == PCM_PLAYBACK &&
1387 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001388 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001389 }
1390 }
1391
1392 return 0;
1393}
1394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395static int stop_output_stream(struct stream_out *out)
1396{
1397 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001398 struct audio_usecase *uc_info;
1399 struct audio_device *adev = out->dev;
1400
Eric Laurent994a6932013-07-17 11:51:42 -07001401 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001402 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001403 uc_info = get_usecase_from_list(adev, out->usecase);
1404 if (uc_info == NULL) {
1405 ALOGE("%s: Could not find the usecase (%d) in the list",
1406 __func__, out->usecase);
1407 return -EINVAL;
1408 }
1409
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001410 if (is_offload_usecase(out->usecase) &&
1411 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001412 if (adev->visualizer_stop_output != NULL)
1413 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001414
1415 audio_extn_dts_remove_state_notifier_node(out->usecase);
1416
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001417 if (adev->offload_effects_stop_output != NULL)
1418 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1419 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001420
Eric Laurent150dbfe2013-02-27 14:31:02 -08001421 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001423
1424 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001425 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001427 list_remove(&uc_info->list);
1428 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001430 if (is_offload_usecase(out->usecase) &&
1431 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1432 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1433 ALOGV("Disable passthrough , reset mixer to pcm");
1434 /* NO_PASSTHROUGH */
1435 out->compr_config.codec->compr_passthr = 0;
1436 audio_extn_dolby_set_hdmi_config(adev, out);
1437 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1438 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001439 /* Must be called after removing the usecase from list */
1440 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1441 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1442
Eric Laurent994a6932013-07-17 11:51:42 -07001443 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 return ret;
1445}
1446
1447int start_output_stream(struct stream_out *out)
1448{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001450 int sink_channels = 0;
1451 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 struct audio_usecase *uc_info;
1453 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301454 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001456 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1457 ret = -EINVAL;
1458 goto error_config;
1459 }
1460
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301461 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1462 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1463 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301464
Naresh Tanniru80659832014-06-04 18:17:56 +05301465 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301466 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301467 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301468 goto error_config;
1469 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301470
Eric Laurentb23d5282013-05-14 15:27:20 -07001471 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472 if (out->pcm_device_id < 0) {
1473 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1474 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001475 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001476 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477 }
1478
1479 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001480
1481 if (!uc_info) {
1482 ret = -ENOMEM;
1483 goto error_config;
1484 }
1485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 uc_info->id = out->usecase;
1487 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001488 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001489 uc_info->devices = out->devices;
1490 uc_info->in_snd_device = SND_DEVICE_NONE;
1491 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001492 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001493 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001494 if (is_offload_usecase(out->usecase)) {
1495 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001496 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1497 }
1498 }
Mingming Yin9c041392014-05-01 15:37:31 -07001499 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1500 if (!strncmp("true", prop_value, 4)) {
1501 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001502 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1503 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001504 check_and_set_hdmi_channels(adev, sink_channels);
1505 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001506 if (is_offload_usecase(out->usecase)) {
1507 unsigned int ch_count = out->compr_config.codec->ch_in;
1508 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1509 /* backend channel config for passthrough stream is stereo */
1510 ch_count = 2;
1511 check_and_set_hdmi_channels(adev, ch_count);
1512 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001513 check_and_set_hdmi_channels(adev, out->config.channels);
1514 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001515 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001516 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001517 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 select_devices(adev, out->usecase);
1520
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001521 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1522 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001523 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001524 unsigned int flags = PCM_OUT;
1525 unsigned int pcm_open_retry_count = 0;
1526 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1527 flags |= PCM_MMAP | PCM_NOIRQ;
1528 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1529 } else
1530 flags |= PCM_MONOTONIC;
1531
1532 while (1) {
1533 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1534 flags, &out->config);
1535 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1536 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1537 if (out->pcm != NULL) {
1538 pcm_close(out->pcm);
1539 out->pcm = NULL;
1540 }
1541 if (pcm_open_retry_count-- == 0) {
1542 ret = -EIO;
1543 goto error_open;
1544 }
1545 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1546 continue;
1547 }
1548 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001549 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001550 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1551 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001553 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1554 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001556 out->compr = compress_open(adev->snd_card,
1557 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001558 COMPRESS_IN, &out->compr_config);
1559 if (out->compr && !is_compress_ready(out->compr)) {
1560 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1561 compress_close(out->compr);
1562 out->compr = NULL;
1563 ret = -EIO;
1564 goto error_open;
1565 }
1566 if (out->offload_callback)
1567 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001568
Fred Oh3f43e742015-03-04 18:42:34 -08001569 /* Since small bufs uses blocking writes, a write will be blocked
1570 for the default max poll time (20s) in the event of an SSR.
1571 Reduce the poll time to observe and deal with SSR faster.
1572 */
1573 if (out->use_small_bufs) {
1574 compress_set_max_poll_wait(out->compr, 1000);
1575 }
1576
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001577 audio_extn_dts_create_state_notifier_node(out->usecase);
1578 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1579 popcount(out->channel_mask),
1580 out->playback_started);
1581
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001582#ifdef DS1_DOLBY_DDP_ENABLED
1583 if (audio_extn_is_dolby_format(out->format))
1584 audio_extn_dolby_send_ddp_endp_params(adev);
1585#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001586 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1587 if (adev->visualizer_start_output != NULL)
1588 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1589 if (adev->offload_effects_start_output != NULL)
1590 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001591 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001592 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 }
Eric Laurent994a6932013-07-17 11:51:42 -07001594 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001598error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001599 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600}
1601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602static int check_input_parameters(uint32_t sample_rate,
1603 audio_format_t format,
1604 int channel_count)
1605{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001606 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001608 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001609 !voice_extn_compress_voip_is_format_supported(format) &&
1610 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001611
1612 switch (channel_count) {
1613 case 1:
1614 case 2:
1615 case 6:
1616 break;
1617 default:
1618 ret = -EINVAL;
1619 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620
1621 switch (sample_rate) {
1622 case 8000:
1623 case 11025:
1624 case 12000:
1625 case 16000:
1626 case 22050:
1627 case 24000:
1628 case 32000:
1629 case 44100:
1630 case 48000:
1631 break;
1632 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001633 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 }
1635
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637}
1638
1639static size_t get_input_buffer_size(uint32_t sample_rate,
1640 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001641 int channel_count,
1642 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643{
1644 size_t size = 0;
1645
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001646 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1647 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001649 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001650 if (is_low_latency)
1651 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001652 /* ToDo: should use frame_size computed based on the format and
1653 channel_count here. */
1654 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001656 /* make sure the size is multiple of 32 bytes
1657 * At 48 kHz mono 16-bit PCM:
1658 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1659 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1660 */
1661 size += 0x1f;
1662 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001663
1664 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665}
1666
1667static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1668{
1669 struct stream_out *out = (struct stream_out *)stream;
1670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672}
1673
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001674static int out_set_sample_rate(struct audio_stream *stream __unused,
1675 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676{
1677 return -ENOSYS;
1678}
1679
1680static size_t out_get_buffer_size(const struct audio_stream *stream)
1681{
1682 struct stream_out *out = (struct stream_out *)stream;
1683
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001684 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001685 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001686 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1687 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001688
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001689 return out->config.period_size *
1690 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691}
1692
1693static uint32_t out_get_channels(const struct audio_stream *stream)
1694{
1695 struct stream_out *out = (struct stream_out *)stream;
1696
1697 return out->channel_mask;
1698}
1699
1700static audio_format_t out_get_format(const struct audio_stream *stream)
1701{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001702 struct stream_out *out = (struct stream_out *)stream;
1703
1704 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705}
1706
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001707static int out_set_format(struct audio_stream *stream __unused,
1708 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709{
1710 return -ENOSYS;
1711}
1712
1713static int out_standby(struct audio_stream *stream)
1714{
1715 struct stream_out *out = (struct stream_out *)stream;
1716 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301718 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1719 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001720 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1721 /* Ignore standby in case of voip call because the voip output
1722 * stream is closed in adev_close_output_stream()
1723 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301724 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001725 return 0;
1726 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001730 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001732 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 if (out->pcm) {
1734 pcm_close(out->pcm);
1735 out->pcm = NULL;
1736 }
1737 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001738 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001740 out->gapless_mdata.encoder_delay = 0;
1741 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742 if (out->compr != NULL) {
1743 compress_close(out->compr);
1744 out->compr = NULL;
1745 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001746 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001748 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 }
1750 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 return 0;
1753}
1754
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001755static int out_dump(const struct audio_stream *stream __unused,
1756 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757{
1758 return 0;
1759}
1760
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001761static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1762{
1763 int ret = 0;
1764 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001765 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001766 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001767 tmp_mdata.encoder_delay = 0;
1768 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001769 tmp_mdata.min_blk_size = 0;
1770 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001771
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001772 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001773 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001774 return -EINVAL;
1775 }
1776
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001777 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1778 if (ret >= 0) {
1779 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1780 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1781 ALOGV("ADTS format is set in offload mode");
1782 }
1783 out->send_new_metadata = 1;
1784 }
1785
Mingming Yin3ee55c62014-08-04 14:23:35 -07001786 if (out->format == AUDIO_FORMAT_FLAC) {
1787 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1788 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001789 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001790 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1791 out->send_new_metadata = 1;
1792 }
1793 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1794 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001795 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001796 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1797 out->send_new_metadata = 1;
1798 }
1799 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1800 if (ret >= 0) {
1801 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1802 out->send_new_metadata = 1;
1803 }
1804 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1805 if (ret >= 0) {
1806 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1807 out->send_new_metadata = 1;
1808 }
1809 }
1810
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001811 if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1812 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1813 if (ret >= 0) {
1814 out->compr_config.codec->format = atoi(value);
1815 out->send_new_metadata = 1;
1816 }
1817 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1818 if (ret >= 0) {
1819 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1820 out->send_new_metadata = 1;
1821 }
1822 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1823 if (ret >= 0) {
1824 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1825 out->send_new_metadata = 1;
1826 }
1827 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1828 if (ret >= 0) {
1829 out->compr_config.codec->options.wma.channelmask = atoi(value);
1830 out->send_new_metadata = 1;
1831 }
1832 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1833 if (ret >= 0) {
1834 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1835 out->send_new_metadata = 1;
1836 }
1837 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1838 if (ret >= 0) {
1839 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1840 out->send_new_metadata = 1;
1841 }
1842 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1843 if (ret >= 0) {
1844 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1845 out->send_new_metadata = 1;
1846 }
1847 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1848 out->compr_config.codec->format,
1849 out->compr_config.codec->options.wma.super_block_align,
1850 out->compr_config.codec->options.wma.bits_per_sample,
1851 out->compr_config.codec->options.wma.channelmask,
1852 out->compr_config.codec->options.wma.encodeopt,
1853 out->compr_config.codec->options.wma.encodeopt1,
1854 out->compr_config.codec->options.wma.encodeopt2);
1855 }
1856
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001857 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1858 if(ret >= 0)
1859 is_meta_data_params = true;
1860 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1861 if(ret >= 0 )
1862 is_meta_data_params = true;
1863 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1864 if(ret >= 0 )
1865 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1867 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001868 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001869 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001870 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001871 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1872 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001873 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001874 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001875 }
1876
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001877 if(!is_meta_data_params) {
1878 ALOGV("%s: Not gapless meta data params", __func__);
1879 return 0;
1880 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001881 out->gapless_mdata = tmp_mdata;
1882 out->send_new_metadata = 1;
1883 ALOGV("%s new encoder delay %u and padding %u", __func__,
1884 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1885
1886 return 0;
1887}
1888
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001889static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1890{
1891 return out == adev->primary_output || out == adev->voice_tx_output;
1892}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1895{
1896 struct stream_out *out = (struct stream_out *)stream;
1897 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001898 struct audio_usecase *usecase;
1899 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900 struct str_parms *parms;
1901 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001902 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001903 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904
sangwoobc677242013-08-08 16:53:43 +09001905 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001906 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301908 if (!parms)
1909 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001910 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1911 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001914 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301917 * When HDMI cable is unplugged/usb hs is disconnected the
1918 * music playback is paused and the policy manager sends routing=0
1919 * But the audioflingercontinues to write data until standby time
1920 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001921 * Avoid this by routing audio to speaker until standby.
1922 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301923 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1924 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001926 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1927 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001928 }
1929
1930 /*
1931 * select_devices() call below switches all the usecases on the same
1932 * backend to the new device. Refer to check_usecases_codec_backend() in
1933 * the select_devices(). But how do we undo this?
1934 *
1935 * For example, music playback is active on headset (deep-buffer usecase)
1936 * and if we go to ringtones and select a ringtone, low-latency usecase
1937 * will be started on headset+speaker. As we can't enable headset+speaker
1938 * and headset devices at the same time, select_devices() switches the music
1939 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1940 * So when the ringtone playback is completed, how do we undo the same?
1941 *
1942 * We are relying on the out_set_parameters() call on deep-buffer output,
1943 * once the ringtone playback is ended.
1944 * NOTE: We should not check if the current devices are same as new devices.
1945 * Because select_devices() must be called to switch back the music
1946 * playback to headset.
1947 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001948 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949 out->devices = val;
1950
1951 if (!out->standby)
1952 select_devices(adev, out->usecase);
1953
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001954 if (output_drives_call(adev, out)) {
1955 if(!voice_is_in_call(adev)) {
1956 if (adev->mode == AUDIO_MODE_IN_CALL) {
1957 adev->current_call_output = out;
1958 ret = voice_start_call(adev);
1959 }
1960 } else {
1961 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001962 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001963 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001964 }
1965 }
1966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001968 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001970
1971 if (out == adev->primary_output) {
1972 pthread_mutex_lock(&adev->lock);
1973 audio_extn_set_parameters(adev, parms);
1974 pthread_mutex_unlock(&adev->lock);
1975 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001976 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001977 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001978 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001979
1980 audio_extn_dts_create_state_notifier_node(out->usecase);
1981 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1982 popcount(out->channel_mask),
1983 out->playback_started);
1984
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001985 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001986 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301989error:
Eric Laurent994a6932013-07-17 11:51:42 -07001990 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 return ret;
1992}
1993
1994static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1995{
1996 struct stream_out *out = (struct stream_out *)stream;
1997 struct str_parms *query = str_parms_create_str(keys);
1998 char *str;
1999 char value[256];
2000 struct str_parms *reply = str_parms_create();
2001 size_t i, j;
2002 int ret;
2003 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002004
2005 if (!query || !reply) {
2006 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2007 return NULL;
2008 }
2009
Eric Laurent994a6932013-07-17 11:51:42 -07002010 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2012 if (ret >= 0) {
2013 value[0] = '\0';
2014 i = 0;
2015 while (out->supported_channel_masks[i] != 0) {
2016 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2017 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2018 if (!first) {
2019 strcat(value, "|");
2020 }
2021 strcat(value, out_channels_name_to_enum_table[j].name);
2022 first = false;
2023 break;
2024 }
2025 }
2026 i++;
2027 }
2028 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2029 str = str_parms_to_str(reply);
2030 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002031 voice_extn_out_get_parameters(out, query, reply);
2032 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002033 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002034 free(str);
2035 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002038
2039 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2040 if (ret >= 0) {
2041 value[0] = '\0';
2042 i = 0;
2043 first = true;
2044 while (out->supported_formats[i] != 0) {
2045 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2046 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2047 if (!first) {
2048 strcat(value, "|");
2049 }
2050 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2051 first = false;
2052 break;
2053 }
2054 }
2055 i++;
2056 }
2057 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2058 str = str_parms_to_str(reply);
2059 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 str_parms_destroy(query);
2061 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002062 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 return str;
2064}
2065
2066static uint32_t out_get_latency(const struct audio_stream_out *stream)
2067{
2068 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002069 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070
Alexy Josephaa54c872014-12-03 02:46:47 -08002071 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002072 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002073 } else {
2074 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002076 }
2077
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302078 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002079 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080}
2081
2082static int out_set_volume(struct audio_stream_out *stream, float left,
2083 float right)
2084{
Eric Laurenta9024de2013-04-04 09:19:12 -07002085 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002086 int volume[2];
2087
Eric Laurenta9024de2013-04-04 09:19:12 -07002088 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2089 /* only take left channel into account: the API is for stereo anyway */
2090 out->muted = (left == 0.0f);
2091 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002092 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002093 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2094 /*
2095 * Set mute or umute on HDMI passthrough stream.
2096 * Only take left channel into account.
2097 * Mute is 0 and unmute 1
2098 */
2099 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2100 } else {
2101 char mixer_ctl_name[128];
2102 struct audio_device *adev = out->dev;
2103 struct mixer_ctl *ctl;
2104 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002105 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002107 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2108 "Compress Playback %d Volume", pcm_device_id);
2109 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2110 if (!ctl) {
2111 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2112 __func__, mixer_ctl_name);
2113 return -EINVAL;
2114 }
2115 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2116 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2117 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2118 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002120 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 return -ENOSYS;
2123}
2124
2125static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2126 size_t bytes)
2127{
2128 struct stream_out *out = (struct stream_out *)stream;
2129 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302130 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002131 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302134
Naresh Tanniru80659832014-06-04 18:17:56 +05302135 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002136 // increase written size during SSR to avoid mismatch
2137 // with the written frames count in AF
2138 if (!is_offload_usecase(out->usecase))
2139 out->written += bytes / (out->config.channels * sizeof(short));
2140
Naresh Tanniru80659832014-06-04 18:17:56 +05302141 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302142 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302143 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302144 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002145 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302146 //during SSR for compress usecase we should return error to flinger
2147 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2148 pthread_mutex_unlock(&out->lock);
2149 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302150 }
2151 }
2152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002154 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002155 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002156 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2157 ret = voice_extn_compress_voip_start_output_stream(out);
2158 else
2159 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002160 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002163 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 goto exit;
2165 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002168 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002169 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002171 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002172 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2173 out->send_new_metadata = 0;
2174 }
2175
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002176 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302177 if (ret < 0)
2178 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002179 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002180 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302181 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302183 } else if (-ENETRESET == ret) {
2184 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2185 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2186 pthread_mutex_unlock(&out->lock);
2187 out_standby(&out->stream.common);
2188 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302190 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002192 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 out->playback_started = 1;
2194 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002195
2196 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2197 popcount(out->channel_mask),
2198 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 }
2200 pthread_mutex_unlock(&out->lock);
2201 return ret;
2202 } else {
2203 if (out->pcm) {
2204 if (out->muted)
2205 memset((void *)buffer, 0, bytes);
2206 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002207 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2208 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2209 else
2210 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302211 if (ret < 0)
2212 ret = -errno;
2213 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002214 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216 }
2217
2218exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302219 /* ToDo: There may be a corner case when SSR happens back to back during
2220 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302221 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302223 }
2224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 pthread_mutex_unlock(&out->lock);
2226
2227 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002228 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002229 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302230 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302231 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302232 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302233 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302234 out->standby = true;
2235 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002237 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302238 out_get_sample_rate(&out->stream.common));
2239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 }
2241 return bytes;
2242}
2243
2244static int out_get_render_position(const struct audio_stream_out *stream,
2245 uint32_t *dsp_frames)
2246{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002247 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302248 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002249 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002250 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002251 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002252 pthread_mutex_lock(&out->lock);
2253 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302254 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302256 if (ret < 0)
2257 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 ALOGVV("%s rendered frames %d sample_rate %d",
2259 __func__, *dsp_frames, out->sample_rate);
2260 }
2261 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302262 if (-ENETRESET == ret) {
2263 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2264 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2265 return -EINVAL;
2266 } else if(ret < 0) {
2267 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2268 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302269 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2270 /*
2271 * Handle corner case where compress session is closed during SSR
2272 * and timestamp is queried
2273 */
2274 ALOGE(" ERROR: sound card not active, return error");
2275 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302276 } else {
2277 return 0;
2278 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002279 } else
2280 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281}
2282
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002283static int out_add_audio_effect(const struct audio_stream *stream __unused,
2284 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285{
2286 return 0;
2287}
2288
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002289static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2290 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291{
2292 return 0;
2293}
2294
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002295static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2296 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297{
2298 return -EINVAL;
2299}
2300
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002301static int out_get_presentation_position(const struct audio_stream_out *stream,
2302 uint64_t *frames, struct timespec *timestamp)
2303{
2304 struct stream_out *out = (struct stream_out *)stream;
2305 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002306 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002307
2308 pthread_mutex_lock(&out->lock);
2309
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002310 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002311 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302312 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002313 &out->sample_rate);
2314 ALOGVV("%s rendered frames %ld sample_rate %d",
2315 __func__, dsp_frames, out->sample_rate);
2316 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302317 if (ret < 0)
2318 ret = -errno;
2319 if (-ENETRESET == ret) {
2320 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2321 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2322 ret = -EINVAL;
2323 } else
2324 ret = 0;
2325
Eric Laurent949a0892013-09-20 09:20:13 -07002326 /* this is the best we can do */
2327 clock_gettime(CLOCK_MONOTONIC, timestamp);
2328 }
2329 } else {
2330 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002331 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002332 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2333 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002334 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002335 // This adjustment accounts for buffering after app processor.
2336 // It is based on estimated DSP latency per use case, rather than exact.
2337 signed_frames -=
2338 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2339
Eric Laurent949a0892013-09-20 09:20:13 -07002340 // It would be unusual for this value to be negative, but check just in case ...
2341 if (signed_frames >= 0) {
2342 *frames = signed_frames;
2343 ret = 0;
2344 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002345 }
2346 }
2347 }
2348
2349 pthread_mutex_unlock(&out->lock);
2350
2351 return ret;
2352}
2353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354static int out_set_callback(struct audio_stream_out *stream,
2355 stream_callback_t callback, void *cookie)
2356{
2357 struct stream_out *out = (struct stream_out *)stream;
2358
2359 ALOGV("%s", __func__);
2360 pthread_mutex_lock(&out->lock);
2361 out->offload_callback = callback;
2362 out->offload_cookie = cookie;
2363 pthread_mutex_unlock(&out->lock);
2364 return 0;
2365}
2366
2367static int out_pause(struct audio_stream_out* stream)
2368{
2369 struct stream_out *out = (struct stream_out *)stream;
2370 int status = -ENOSYS;
2371 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002372 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002373 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 pthread_mutex_lock(&out->lock);
2375 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302376 struct audio_device *adev = out->dev;
2377 int snd_scard_state = get_snd_card_state(adev);
2378
2379 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2380 status = compress_pause(out->compr);
2381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002382 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002383
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302384 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002385 audio_extn_dts_notify_playback_state(out->usecase, 0,
2386 out->sample_rate, popcount(out->channel_mask),
2387 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 }
2389 pthread_mutex_unlock(&out->lock);
2390 }
2391 return status;
2392}
2393
2394static int out_resume(struct audio_stream_out* stream)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397 int status = -ENOSYS;
2398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002400 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 status = 0;
2402 pthread_mutex_lock(&out->lock);
2403 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302404 struct audio_device *adev = out->dev;
2405 int snd_scard_state = get_snd_card_state(adev);
2406
2407 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2408 status = compress_resume(out->compr);
2409
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002411
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302412 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002413 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2414 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 }
2416 pthread_mutex_unlock(&out->lock);
2417 }
2418 return status;
2419}
2420
2421static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2422{
2423 struct stream_out *out = (struct stream_out *)stream;
2424 int status = -ENOSYS;
2425 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002426 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002427 pthread_mutex_lock(&out->lock);
2428 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2429 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2430 else
2431 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2432 pthread_mutex_unlock(&out->lock);
2433 }
2434 return status;
2435}
2436
2437static int out_flush(struct audio_stream_out* stream)
2438{
2439 struct stream_out *out = (struct stream_out *)stream;
2440 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002441 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002442 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443 pthread_mutex_lock(&out->lock);
2444 stop_compressed_output_l(out);
2445 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002446 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 return 0;
2448 }
2449 return -ENOSYS;
2450}
2451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452/** audio_stream_in implementation **/
2453static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2454{
2455 struct stream_in *in = (struct stream_in *)stream;
2456
2457 return in->config.rate;
2458}
2459
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002460static int in_set_sample_rate(struct audio_stream *stream __unused,
2461 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462{
2463 return -ENOSYS;
2464}
2465
2466static size_t in_get_buffer_size(const struct audio_stream *stream)
2467{
2468 struct stream_in *in = (struct stream_in *)stream;
2469
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002470 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2471 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002472 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2473 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002474
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002475 return in->config.period_size *
2476 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477}
2478
2479static uint32_t in_get_channels(const struct audio_stream *stream)
2480{
2481 struct stream_in *in = (struct stream_in *)stream;
2482
2483 return in->channel_mask;
2484}
2485
2486static audio_format_t in_get_format(const struct audio_stream *stream)
2487{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002488 struct stream_in *in = (struct stream_in *)stream;
2489
2490 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491}
2492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002493static int in_set_format(struct audio_stream *stream __unused,
2494 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495{
2496 return -ENOSYS;
2497}
2498
2499static int in_standby(struct audio_stream *stream)
2500{
2501 struct stream_in *in = (struct stream_in *)stream;
2502 struct audio_device *adev = in->dev;
2503 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302504 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2505 stream, in->usecase, use_case_table[in->usecase]);
2506
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002507 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2508 /* Ignore standby in case of voip call because the voip input
2509 * stream is closed in adev_close_input_stream()
2510 */
2511 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2512 return status;
2513 }
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002516 if (!in->standby && in->is_st_session) {
2517 ALOGD("%s: sound trigger pcm stop lab", __func__);
2518 audio_extn_sound_trigger_stop_lab(in);
2519 in->standby = 1;
2520 }
2521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002523 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002525 if (in->pcm) {
2526 pcm_close(in->pcm);
2527 in->pcm = NULL;
2528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002530 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 }
2532 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002533 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 return status;
2535}
2536
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002537static int in_dump(const struct audio_stream *stream __unused,
2538 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539{
2540 return 0;
2541}
2542
2543static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2544{
2545 struct stream_in *in = (struct stream_in *)stream;
2546 struct audio_device *adev = in->dev;
2547 struct str_parms *parms;
2548 char *str;
2549 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002550 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302552 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 parms = str_parms_create_str(kvpairs);
2554
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302555 if (!parms)
2556 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002558 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002559
2560 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2561 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 val = atoi(value);
2563 /* no audio source uses val == 0 */
2564 if ((in->source != val) && (val != 0)) {
2565 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002566 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2567 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2568 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2569 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002570 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002571 err = voice_extn_compress_voip_open_input_stream(in);
2572 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002573 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002574 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002575 }
2576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
2578 }
2579
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002580 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2581 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002583 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 in->device = val;
2585 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002586 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002587 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588 }
2589 }
2590
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002591done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002593 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594
2595 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302596error:
Eric Laurent994a6932013-07-17 11:51:42 -07002597 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 return ret;
2599}
2600
2601static char* in_get_parameters(const struct audio_stream *stream,
2602 const char *keys)
2603{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002604 struct stream_in *in = (struct stream_in *)stream;
2605 struct str_parms *query = str_parms_create_str(keys);
2606 char *str;
2607 char value[256];
2608 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002609
2610 if (!query || !reply) {
2611 ALOGE("in_get_parameters: failed to create query or reply");
2612 return NULL;
2613 }
2614
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002615 ALOGV("%s: enter: keys - %s", __func__, keys);
2616
2617 voice_extn_in_get_parameters(in, query, reply);
2618
2619 str = str_parms_to_str(reply);
2620 str_parms_destroy(query);
2621 str_parms_destroy(reply);
2622
2623 ALOGV("%s: exit: returns - %s", __func__, str);
2624 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625}
2626
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002627static int in_set_gain(struct audio_stream_in *stream __unused,
2628 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629{
2630 return 0;
2631}
2632
2633static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2634 size_t bytes)
2635{
2636 struct stream_in *in = (struct stream_in *)stream;
2637 struct audio_device *adev = in->dev;
2638 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302639 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302642
2643 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302644 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302645 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302646 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302647 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002648 } else {
2649 if (in->is_st_session && !in->is_st_session_active) {
2650 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2651 ret= -EIO;;
2652 goto exit;
2653 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302654 }
2655 }
2656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002658 if (!in->is_st_session) {
2659 pthread_mutex_lock(&adev->lock);
2660 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2661 ret = voice_extn_compress_voip_start_input_stream(in);
2662 else
2663 ret = start_input_stream(in);
2664 pthread_mutex_unlock(&adev->lock);
2665 if (ret != 0) {
2666 goto exit;
2667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 }
2669 in->standby = 0;
2670 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671
2672 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002673 if (audio_extn_ssr_get_enabled() &&
2674 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002675 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002676 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2677 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002678 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2679 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002680 else
2681 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302682 if (ret < 0)
2683 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 }
2685
2686 /*
2687 * Instead of writing zeroes here, we could trust the hardware
2688 * to always provide zeroes when muted.
2689 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302690 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2691 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 memset(buffer, 0, bytes);
2693
2694exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302695 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302696 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302697 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002698 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2699 session reading on LAB data. In this case do not set sound card state
2700 offline, instead mark this sound trigger session inactive to avoid
2701 further reading of LAB data from CPE driver. Marking the session
2702 inactive handles both CPE and ADSP SSR for sound trigger session */
2703 if (!in->is_st_session)
2704 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2705 else
2706 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302707 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 pthread_mutex_unlock(&in->lock);
2709
2710 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302711 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302712 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302713 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302714 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302715 in->standby = true;
2716 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302717 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002719 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002720 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302721 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 }
2723 return bytes;
2724}
2725
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002726static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727{
2728 return 0;
2729}
2730
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002731static int add_remove_audio_effect(const struct audio_stream *stream,
2732 effect_handle_t effect,
2733 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002735 struct stream_in *in = (struct stream_in *)stream;
2736 int status = 0;
2737 effect_descriptor_t desc;
2738
2739 status = (*effect)->get_descriptor(effect, &desc);
2740 if (status != 0)
2741 return status;
2742
2743 pthread_mutex_lock(&in->lock);
2744 pthread_mutex_lock(&in->dev->lock);
2745 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2746 in->enable_aec != enable &&
2747 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2748 in->enable_aec = enable;
2749 if (!in->standby)
2750 select_devices(in->dev, in->usecase);
2751 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002752 if (in->enable_ns != enable &&
2753 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2754 in->enable_ns = enable;
2755 if (!in->standby)
2756 select_devices(in->dev, in->usecase);
2757 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002758 pthread_mutex_unlock(&in->dev->lock);
2759 pthread_mutex_unlock(&in->lock);
2760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 return 0;
2762}
2763
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002764static int in_add_audio_effect(const struct audio_stream *stream,
2765 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766{
Eric Laurent994a6932013-07-17 11:51:42 -07002767 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002768 return add_remove_audio_effect(stream, effect, true);
2769}
2770
2771static int in_remove_audio_effect(const struct audio_stream *stream,
2772 effect_handle_t effect)
2773{
Eric Laurent994a6932013-07-17 11:51:42 -07002774 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002775 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776}
2777
2778static int adev_open_output_stream(struct audio_hw_device *dev,
2779 audio_io_handle_t handle,
2780 audio_devices_t devices,
2781 audio_output_flags_t flags,
2782 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002783 struct audio_stream_out **stream_out,
2784 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785{
2786 struct audio_device *adev = (struct audio_device *)dev;
2787 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002788 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002789 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302792
2793 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2794 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2795 ALOGE(" sound card is not active rejecting compress output open request");
2796 return -EINVAL;
2797 }
2798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2800
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302801 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2802 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2803 devices, flags, &out->stream);
2804
2805
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002806 if (!out) {
2807 return -ENOMEM;
2808 }
2809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 if (devices == AUDIO_DEVICE_NONE)
2811 devices = AUDIO_DEVICE_OUT_SPEAKER;
2812
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 out->flags = flags;
2814 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002815 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002816 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 out->sample_rate = config->sample_rate;
2818 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2819 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002820 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002821 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002822 out->non_blocking = 0;
2823 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824
2825 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002826 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2827 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2828 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2829
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002830 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002831 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2832 ret = read_hdmi_channel_masks(out);
2833
2834 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2835 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002836 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002837 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002838 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002839
2840 if (config->sample_rate == 0)
2841 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2842 if (config->channel_mask == 0)
2843 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2844
2845 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2848 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002850 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002852 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2853 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002854 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002855 ret = voice_extn_compress_voip_open_output_stream(out);
2856 if (ret != 0) {
2857 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2858 __func__, ret);
2859 goto error_open;
2860 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2862 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2863 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2864 ALOGE("%s: Unsupported Offload information", __func__);
2865 ret = -EINVAL;
2866 goto error_open;
2867 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002868
2869 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2870 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2871 ALOGV("read and update_pass through formats");
2872 ret = audio_extn_dolby_update_passt_formats(adev, out);
2873 if(ret != 0) {
2874 goto error_open;
2875 }
2876 if(config->offload_info.format == 0)
2877 config->offload_info.format = out->supported_formats[0];
2878 }
2879
Mingming Yin90310102013-11-13 16:57:00 -08002880 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002881 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 ALOGE("%s: Unsupported audio format", __func__);
2883 ret = -EINVAL;
2884 goto error_open;
2885 }
2886
2887 out->compr_config.codec = (struct snd_codec *)
2888 calloc(1, sizeof(struct snd_codec));
2889
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002890 if (!out->compr_config.codec) {
2891 ret = -ENOMEM;
2892 goto error_open;
2893 }
2894
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002895 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 if (config->offload_info.channel_mask)
2897 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002898 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002900 config->offload_info.channel_mask = config->channel_mask;
2901 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002902 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 out->sample_rate = config->offload_info.sample_rate;
2904
2905 out->stream.set_callback = out_set_callback;
2906 out->stream.pause = out_pause;
2907 out->stream.resume = out_resume;
2908 out->stream.drain = out_drain;
2909 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002910 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002912 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002913 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002914 audio_extn_dolby_get_snd_codec_id(adev, out,
2915 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002916 else
2917 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002919 if (audio_is_offload_pcm(config->offload_info.format)) {
2920 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002921 platform_get_pcm_offload_buffer_size(&config->offload_info);
2922 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2923 out->compr_config.fragment_size =
2924 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002925 } else {
2926 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002927 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002928 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2930 out->compr_config.codec->sample_rate =
2931 compress_get_alsa_rate(config->offload_info.sample_rate);
2932 out->compr_config.codec->bit_rate =
2933 config->offload_info.bit_rate;
2934 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002935 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002937 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002938 /*TODO: Do we need to change it for passthrough */
2939 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940
Mingming Yin3ee55c62014-08-04 14:23:35 -07002941 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2942 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002943 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2944 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002945 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002946 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2947
Mingming Yin3ee55c62014-08-04 14:23:35 -07002948 if (out->bit_width == 24) {
2949 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2950 }
2951
Amit Shekhar6f461b12014-08-01 14:52:58 -07002952 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002953 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002954
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2956 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002957
Alexy Josephaa54c872014-12-03 02:46:47 -08002958 if (config->offload_info.use_small_bufs) {
2959 //this flag is set from framework only if its for PCM formats
2960 //no need to check for PCM format again
2961 out->non_blocking = 0;
2962 out->use_small_bufs = true;
2963 ALOGI("Keep write blocking for small buff: non_blockling %d",
2964 out->non_blocking);
2965 }
2966
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002967 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002968 out->offload_state = OFFLOAD_STATE_IDLE;
2969 out->playback_started = 0;
2970
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002971 audio_extn_dts_create_state_notifier_node(out->usecase);
2972
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 create_offload_callback_thread(out);
2974 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2975 __func__, config->offload_info.version,
2976 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002977 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002978 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002979 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2980 ret = voice_check_and_set_incall_music_usecase(adev, out);
2981 if (ret != 0) {
2982 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2983 __func__, ret);
2984 goto error_open;
2985 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002986 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2987 if (config->sample_rate == 0)
2988 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2989 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2990 config->sample_rate != 8000) {
2991 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2992 ret = -EINVAL;
2993 goto error_open;
2994 }
2995 out->sample_rate = config->sample_rate;
2996 out->config.rate = config->sample_rate;
2997 if (config->format == AUDIO_FORMAT_DEFAULT)
2998 config->format = AUDIO_FORMAT_PCM_16_BIT;
2999 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3000 config->format = AUDIO_FORMAT_PCM_16_BIT;
3001 ret = -EINVAL;
3002 goto error_open;
3003 }
3004 out->format = config->format;
3005 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3006 out->config = pcm_config_afe_proxy_playback;
3007 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003008 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003009 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3011 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003013 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3014 format = AUDIO_FORMAT_PCM_16_BIT;
3015 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3016 out->config = pcm_config_deep_buffer;
3017 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003018 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003019 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003020 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003021 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003022 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003023 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 }
3025
Amit Shekhar1d896042014-10-03 13:16:09 -07003026 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3027 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003028 /* TODO remove this hardcoding and check why width is zero*/
3029 if (out->bit_width == 0)
3030 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003031 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3032 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003033 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003034 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003035 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3036 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3037 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003038 if(adev->primary_output == NULL)
3039 adev->primary_output = out;
3040 else {
3041 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003042 ret = -EEXIST;
3043 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003044 }
3045 }
3046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 /* Check if this usecase is already existing */
3048 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003049 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3050 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003053 ret = -EEXIST;
3054 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 }
3056 pthread_mutex_unlock(&adev->lock);
3057
3058 out->stream.common.get_sample_rate = out_get_sample_rate;
3059 out->stream.common.set_sample_rate = out_set_sample_rate;
3060 out->stream.common.get_buffer_size = out_get_buffer_size;
3061 out->stream.common.get_channels = out_get_channels;
3062 out->stream.common.get_format = out_get_format;
3063 out->stream.common.set_format = out_set_format;
3064 out->stream.common.standby = out_standby;
3065 out->stream.common.dump = out_dump;
3066 out->stream.common.set_parameters = out_set_parameters;
3067 out->stream.common.get_parameters = out_get_parameters;
3068 out->stream.common.add_audio_effect = out_add_audio_effect;
3069 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3070 out->stream.get_latency = out_get_latency;
3071 out->stream.set_volume = out_set_volume;
3072 out->stream.write = out_write;
3073 out->stream.get_render_position = out_get_render_position;
3074 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003075 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003078 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003079 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003081 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3082 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 config->format = out->stream.common.get_format(&out->stream.common);
3085 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3086 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3087
3088 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303089 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3090 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003091
3092 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3093 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3094 popcount(out->channel_mask), out->playback_started);
3095
Eric Laurent994a6932013-07-17 11:51:42 -07003096 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003098
3099error_open:
3100 free(out);
3101 *stream_out = NULL;
3102 ALOGD("%s: exit: ret %d", __func__, ret);
3103 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104}
3105
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003106static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 struct audio_stream_out *stream)
3108{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109 struct stream_out *out = (struct stream_out *)stream;
3110 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003111 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003112
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303113 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3114
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003115 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303116 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003117 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303118 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003119 if(ret != 0)
3120 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3121 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003122 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003123 out_standby(&stream->common);
3124
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003125 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003126 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003128 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 if (out->compr_config.codec != NULL)
3130 free(out->compr_config.codec);
3131 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003132
3133 if (adev->voice_tx_output == out)
3134 adev->voice_tx_output = NULL;
3135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 pthread_cond_destroy(&out->cond);
3137 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003139 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140}
3141
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003142static void close_compress_sessions(struct audio_device *adev)
3143{
Mingming Yin7b762e72015-03-04 13:47:32 -08003144 struct stream_out *out;
3145 struct listnode *node;
3146 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003147 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003148 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003149 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003150 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003151 if (usecase && usecase->stream.out) {
3152 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3153 out = usecase->stream.out;
3154 pthread_mutex_unlock(&adev->lock);
3155 out_standby(&out->stream.common);
3156 pthread_mutex_lock(&adev->lock);
3157 }
3158 }
3159 }
3160 pthread_mutex_unlock(&adev->lock);
3161}
3162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3164{
3165 struct audio_device *adev = (struct audio_device *)dev;
3166 struct str_parms *parms;
3167 char *str;
3168 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003169 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003170 int ret;
3171 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003173 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303176 if (!parms)
3177 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3179 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303180 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303181 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303182 struct listnode *node;
3183 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303184 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303185 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003186 //close compress sessions on OFFLINE status
3187 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303188 } else if (strstr(snd_card_status, "ONLINE")) {
3189 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303190 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303191 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303192 }
3193
3194 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003195 status = voice_set_parameters(adev, parms);
3196 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003197 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003199 status = platform_set_parameters(adev->platform, parms);
3200 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003201 goto done;
3202
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003203 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3204 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003205 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3207 adev->bluetooth_nrec = true;
3208 else
3209 adev->bluetooth_nrec = false;
3210 }
3211
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003212 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3213 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3215 adev->screen_off = false;
3216 else
3217 adev->screen_off = true;
3218 }
3219
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003220 ret = str_parms_get_int(parms, "rotation", &val);
3221 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003222 bool reverse_speakers = false;
3223 switch(val) {
3224 // FIXME: note that the code below assumes that the speakers are in the correct placement
3225 // relative to the user when the device is rotated 90deg from its default rotation. This
3226 // assumption is device-specific, not platform-specific like this code.
3227 case 270:
3228 reverse_speakers = true;
3229 break;
3230 case 0:
3231 case 90:
3232 case 180:
3233 break;
3234 default:
3235 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003236 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003237 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003238 if (status == 0) {
3239 if (adev->speaker_lr_swap != reverse_speakers) {
3240 adev->speaker_lr_swap = reverse_speakers;
3241 // only update the selected device if there is active pcm playback
3242 struct audio_usecase *usecase;
3243 struct listnode *node;
3244 list_for_each(node, &adev->usecase_list) {
3245 usecase = node_to_item(node, struct audio_usecase, list);
3246 if (usecase->type == PCM_PLAYBACK) {
3247 select_devices(adev, usecase->id);
3248 break;
3249 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003250 }
3251 }
3252 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003253 }
3254
Mingming Yin514a8bc2014-07-29 15:22:21 -07003255 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3256 if (ret >= 0) {
3257 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3258 adev->bt_wb_speech_enabled = true;
3259 else
3260 adev->bt_wb_speech_enabled = false;
3261 }
3262
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003263 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3264 if (ret >= 0) {
3265 val = atoi(value);
3266 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3267 ALOGV("cache new edid");
3268 platform_cache_edid(adev->platform);
3269 }
3270 }
3271
3272 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3273 if (ret >= 0) {
3274 val = atoi(value);
3275 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3276 ALOGV("invalidate cached edid");
3277 platform_invalidate_edid(adev->platform);
3278 }
3279 }
3280
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003281 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003282
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003283done:
3284 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003285 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303286error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003287 ALOGV("%s: exit with code(%d)", __func__, status);
3288 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289}
3290
3291static char* adev_get_parameters(const struct audio_hw_device *dev,
3292 const char *keys)
3293{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003294 struct audio_device *adev = (struct audio_device *)dev;
3295 struct str_parms *reply = str_parms_create();
3296 struct str_parms *query = str_parms_create_str(keys);
3297 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303298 char value[256] = {0};
3299 int ret = 0;
3300
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003301 if (!query || !reply) {
3302 ALOGE("adev_get_parameters: failed to create query or reply");
3303 return NULL;
3304 }
3305
Naresh Tannirud7205b62014-06-20 02:54:48 +05303306 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3307 sizeof(value));
3308 if (ret >=0) {
3309 int val = 1;
3310 pthread_mutex_lock(&adev->snd_card_status.lock);
3311 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3312 val = 0;
3313 pthread_mutex_unlock(&adev->snd_card_status.lock);
3314 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3315 goto exit;
3316 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003317
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003318 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003319 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003320 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003321 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303322 pthread_mutex_unlock(&adev->lock);
3323
Naresh Tannirud7205b62014-06-20 02:54:48 +05303324exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003325 str = str_parms_to_str(reply);
3326 str_parms_destroy(query);
3327 str_parms_destroy(reply);
3328
3329 ALOGV("%s: exit: returns - %s", __func__, str);
3330 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003333static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334{
3335 return 0;
3336}
3337
3338static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3339{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003340 int ret;
3341 struct audio_device *adev = (struct audio_device *)dev;
3342 pthread_mutex_lock(&adev->lock);
3343 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003344 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003345 pthread_mutex_unlock(&adev->lock);
3346 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347}
3348
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003349static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3350 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351{
3352 return -ENOSYS;
3353}
3354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003355static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3356 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357{
3358 return -ENOSYS;
3359}
3360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003361static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3362 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363{
3364 return -ENOSYS;
3365}
3366
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003367static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3368 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369{
3370 return -ENOSYS;
3371}
3372
3373static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3374{
3375 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 pthread_mutex_lock(&adev->lock);
3378 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003379 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003381 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3382 voice_is_in_call(adev)) {
3383 voice_stop_call(adev);
3384 adev->current_call_output = NULL;
3385 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 }
3387 pthread_mutex_unlock(&adev->lock);
3388 return 0;
3389}
3390
3391static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3392{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003393 int ret;
3394
3395 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003396 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003397 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3398 pthread_mutex_unlock(&adev->lock);
3399
3400 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401}
3402
3403static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3404{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003405 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 return 0;
3407}
3408
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003409static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 const struct audio_config *config)
3411{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003412 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003414 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3415 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416}
3417
3418static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003419 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 audio_devices_t devices,
3421 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003422 struct audio_stream_in **stream_in,
3423 audio_input_flags_t flags __unused,
3424 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003425 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426{
3427 struct audio_device *adev = (struct audio_device *)dev;
3428 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003429 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003430 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003431 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433 *stream_in = NULL;
3434 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3435 return -EINVAL;
3436
3437 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003438
3439 if (!in) {
3440 ALOGE("failed to allocate input stream");
3441 return -ENOMEM;
3442 }
3443
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303444 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003445 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3446 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003448 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 in->stream.common.get_sample_rate = in_get_sample_rate;
3451 in->stream.common.set_sample_rate = in_set_sample_rate;
3452 in->stream.common.get_buffer_size = in_get_buffer_size;
3453 in->stream.common.get_channels = in_get_channels;
3454 in->stream.common.get_format = in_get_format;
3455 in->stream.common.set_format = in_set_format;
3456 in->stream.common.standby = in_standby;
3457 in->stream.common.dump = in_dump;
3458 in->stream.common.set_parameters = in_set_parameters;
3459 in->stream.common.get_parameters = in_get_parameters;
3460 in->stream.common.add_audio_effect = in_add_audio_effect;
3461 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3462 in->stream.set_gain = in_set_gain;
3463 in->stream.read = in_read;
3464 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3465
3466 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003467 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469 in->standby = 1;
3470 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003471 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472
3473 /* Update config params with the requested sample rate and channels */
3474 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003475 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3476 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3477 is_low_latency = true;
3478#if LOW_LATENCY_CAPTURE_USE_CASE
3479 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3480#endif
3481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003484 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003486 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303487 if (adev->mode != AUDIO_MODE_IN_CALL) {
3488 ret = -EINVAL;
3489 goto err_open;
3490 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003491 if (config->sample_rate == 0)
3492 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3493 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3494 config->sample_rate != 8000) {
3495 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3496 ret = -EINVAL;
3497 goto err_open;
3498 }
3499 if (config->format == AUDIO_FORMAT_DEFAULT)
3500 config->format = AUDIO_FORMAT_PCM_16_BIT;
3501 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3502 config->format = AUDIO_FORMAT_PCM_16_BIT;
3503 ret = -EINVAL;
3504 goto err_open;
3505 }
3506
3507 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3508 in->config = pcm_config_afe_proxy_record;
3509 in->config.channels = channel_count;
3510 in->config.rate = config->sample_rate;
3511 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003512 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003513 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003514 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3515 ret = -EINVAL;
3516 goto err_open;
3517 }
3518 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003519 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003520 }
Mingming Yine62d7842013-10-25 16:26:03 -07003521 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003522 audio_extn_compr_cap_format_supported(config->format) &&
3523 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003524 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003525 } else {
3526 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003527 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003528 buffer_size = get_input_buffer_size(config->sample_rate,
3529 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003530 channel_count,
3531 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003532 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003533 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3534 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3535 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3536 (in->config.rate == 8000 || in->config.rate == 16000) &&
3537 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3538 voice_extn_compress_voip_open_input_stream(in);
3539 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003540 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003542 /* This stream could be for sound trigger lab,
3543 get sound trigger pcm if present */
3544 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303545 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003548 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003549 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550
3551err_open:
3552 free(in);
3553 *stream_in = NULL;
3554 return ret;
3555}
3556
3557static void adev_close_input_stream(struct audio_hw_device *dev,
3558 struct audio_stream_in *stream)
3559{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003560 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003561 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003562 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303563
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303564 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003565
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303566 /* Disable echo reference while closing input stream */
3567 platform_set_echo_reference(adev->platform, false);
3568
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003569 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303570 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003571 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303572 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003573 if (ret != 0)
3574 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3575 __func__, ret);
3576 } else
3577 in_standby(&stream->common);
3578
Mingming Yin7b762e72015-03-04 13:47:32 -08003579 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003580 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003581 audio_extn_ssr_deinit();
3582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583
Mingming Yine62d7842013-10-25 16:26:03 -07003584 if(audio_extn_compr_cap_enabled() &&
3585 audio_extn_compr_cap_format_supported(in->config.format))
3586 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003587
3588 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 return;
3590}
3591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003592static int adev_dump(const audio_hw_device_t *device __unused,
3593 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594{
3595 return 0;
3596}
3597
3598static int adev_close(hw_device_t *device)
3599{
3600 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003601
3602 if (!adev)
3603 return 0;
3604
3605 pthread_mutex_lock(&adev_init_lock);
3606
3607 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003608 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003609 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003610 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003611 audio_route_free(adev->audio_route);
3612 free(adev->snd_dev_ref_cnt);
3613 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003614 free(device);
3615 adev = NULL;
3616 }
3617 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 return 0;
3619}
3620
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003621/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3622 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3623 * just that it _might_ work.
3624 */
3625static int period_size_is_plausible_for_low_latency(int period_size)
3626{
3627 switch (period_size) {
3628 case 160:
3629 case 240:
3630 case 320:
3631 case 480:
3632 return 1;
3633 default:
3634 return 0;
3635 }
3636}
3637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638static int adev_open(const hw_module_t *module, const char *name,
3639 hw_device_t **device)
3640{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003641 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003643 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3645
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003646 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003647 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003648 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003649 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003650 ALOGD("%s: returning existing instance of adev", __func__);
3651 ALOGD("%s: exit", __func__);
3652 pthread_mutex_unlock(&adev_init_lock);
3653 return 0;
3654 }
3655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 adev = calloc(1, sizeof(struct audio_device));
3657
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003658 if (!adev) {
3659 pthread_mutex_unlock(&adev_init_lock);
3660 return -ENOMEM;
3661 }
3662
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003663 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3666 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3667 adev->device.common.module = (struct hw_module_t *)module;
3668 adev->device.common.close = adev_close;
3669
3670 adev->device.init_check = adev_init_check;
3671 adev->device.set_voice_volume = adev_set_voice_volume;
3672 adev->device.set_master_volume = adev_set_master_volume;
3673 adev->device.get_master_volume = adev_get_master_volume;
3674 adev->device.set_master_mute = adev_set_master_mute;
3675 adev->device.get_master_mute = adev_get_master_mute;
3676 adev->device.set_mode = adev_set_mode;
3677 adev->device.set_mic_mute = adev_set_mic_mute;
3678 adev->device.get_mic_mute = adev_get_mic_mute;
3679 adev->device.set_parameters = adev_set_parameters;
3680 adev->device.get_parameters = adev_get_parameters;
3681 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3682 adev->device.open_output_stream = adev_open_output_stream;
3683 adev->device.close_output_stream = adev_close_output_stream;
3684 adev->device.open_input_stream = adev_open_input_stream;
3685 adev->device.close_input_stream = adev_close_input_stream;
3686 adev->device.dump = adev_dump;
3687
3688 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003690 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003691 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003694 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003695 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003696 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3697 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003698 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003699 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003700 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003701 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003702 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303703
3704 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3705 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003707 adev->platform = platform_init(adev);
3708 if (!adev->platform) {
3709 free(adev->snd_dev_ref_cnt);
3710 free(adev);
3711 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3712 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003713 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003714 return -EINVAL;
3715 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003716
Naresh Tanniru4c630392014-05-12 01:05:52 +05303717 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3718
Eric Laurentc4aef752013-09-12 17:45:53 -07003719 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3720 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3721 if (adev->visualizer_lib == NULL) {
3722 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3723 } else {
3724 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3725 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003726 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003727 "visualizer_hal_start_output");
3728 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003730 "visualizer_hal_stop_output");
3731 }
3732 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003733 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003734 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003735
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003736 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3737 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3738 if (adev->offload_effects_lib == NULL) {
3739 ALOGE("%s: DLOPEN failed for %s", __func__,
3740 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3741 } else {
3742 ALOGV("%s: DLOPEN successful for %s", __func__,
3743 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3744 adev->offload_effects_start_output =
3745 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3746 "offload_effects_bundle_hal_start_output");
3747 adev->offload_effects_stop_output =
3748 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3749 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003750 adev->offload_effects_set_hpx_state =
3751 (int (*)(bool))dlsym(adev->offload_effects_lib,
3752 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003753 }
3754 }
3755
Mingming Yin514a8bc2014-07-29 15:22:21 -07003756 adev->bt_wb_speech_enabled = false;
3757
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003758 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 *device = &adev->device.common;
3760
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003761 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3762 &adev->streams_output_cfg_list);
3763
Kiran Kandi910e1862013-10-29 13:29:42 -07003764 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003765
3766 char value[PROPERTY_VALUE_MAX];
3767 int trial;
3768 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3769 trial = atoi(value);
3770 if (period_size_is_plausible_for_low_latency(trial)) {
3771 pcm_config_low_latency.period_size = trial;
3772 pcm_config_low_latency.start_threshold = trial / 4;
3773 pcm_config_low_latency.avail_min = trial / 4;
3774 configured_low_latency_capture_period_size = trial;
3775 }
3776 }
3777 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3778 trial = atoi(value);
3779 if (period_size_is_plausible_for_low_latency(trial)) {
3780 configured_low_latency_capture_period_size = trial;
3781 }
3782 }
3783
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003784 pthread_mutex_unlock(&adev_init_lock);
3785
Eric Laurent994a6932013-07-17 11:51:42 -07003786 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 return 0;
3788}
3789
3790static struct hw_module_methods_t hal_module_methods = {
3791 .open = adev_open,
3792};
3793
3794struct audio_module HAL_MODULE_INFO_SYM = {
3795 .common = {
3796 .tag = HARDWARE_MODULE_TAG,
3797 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3798 .hal_api_version = HARDWARE_HAL_API_VERSION,
3799 .id = AUDIO_HARDWARE_MODULE_ID,
3800 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003801 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 .methods = &hal_module_methods,
3803 },
3804};