blob: 4f69bd524300877f6bf94f9f8fc26b3c4e15e540 [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;
Zhou Song32a556e2015-05-05 10:46:56 +08002249
2250 if (dsp_frames == NULL)
2251 return -EINVAL;
2252
2253 *dsp_frames = 0;
2254 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002255 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002256 pthread_mutex_lock(&out->lock);
2257 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302258 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002259 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302260 if (ret < 0)
2261 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002262 ALOGVV("%s rendered frames %d sample_rate %d",
2263 __func__, *dsp_frames, out->sample_rate);
2264 }
2265 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302266 if (-ENETRESET == ret) {
2267 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2268 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2269 return -EINVAL;
2270 } else if(ret < 0) {
2271 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2272 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302273 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2274 /*
2275 * Handle corner case where compress session is closed during SSR
2276 * and timestamp is queried
2277 */
2278 ALOGE(" ERROR: sound card not active, return error");
2279 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302280 } else {
2281 return 0;
2282 }
Zhou Song32a556e2015-05-05 10:46:56 +08002283 } else if (audio_is_linear_pcm(out->format)) {
2284 *dsp_frames = out->written;
2285 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 } else
2287 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288}
2289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002290static int out_add_audio_effect(const struct audio_stream *stream __unused,
2291 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002292{
2293 return 0;
2294}
2295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002296static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2297 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298{
2299 return 0;
2300}
2301
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002302static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2303 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304{
2305 return -EINVAL;
2306}
2307
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002308static int out_get_presentation_position(const struct audio_stream_out *stream,
2309 uint64_t *frames, struct timespec *timestamp)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002313 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002314
2315 pthread_mutex_lock(&out->lock);
2316
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002317 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002318 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302319 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002320 &out->sample_rate);
2321 ALOGVV("%s rendered frames %ld sample_rate %d",
2322 __func__, dsp_frames, out->sample_rate);
2323 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302324 if (ret < 0)
2325 ret = -errno;
2326 if (-ENETRESET == ret) {
2327 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2328 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2329 ret = -EINVAL;
2330 } else
2331 ret = 0;
2332
Eric Laurent949a0892013-09-20 09:20:13 -07002333 /* this is the best we can do */
2334 clock_gettime(CLOCK_MONOTONIC, timestamp);
2335 }
2336 } else {
2337 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002338 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002339 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2340 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002341 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002342 // This adjustment accounts for buffering after app processor.
2343 // It is based on estimated DSP latency per use case, rather than exact.
2344 signed_frames -=
2345 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2346
Eric Laurent949a0892013-09-20 09:20:13 -07002347 // It would be unusual for this value to be negative, but check just in case ...
2348 if (signed_frames >= 0) {
2349 *frames = signed_frames;
2350 ret = 0;
2351 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002352 }
2353 }
2354 }
2355
2356 pthread_mutex_unlock(&out->lock);
2357
2358 return ret;
2359}
2360
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361static int out_set_callback(struct audio_stream_out *stream,
2362 stream_callback_t callback, void *cookie)
2363{
2364 struct stream_out *out = (struct stream_out *)stream;
2365
2366 ALOGV("%s", __func__);
2367 pthread_mutex_lock(&out->lock);
2368 out->offload_callback = callback;
2369 out->offload_cookie = cookie;
2370 pthread_mutex_unlock(&out->lock);
2371 return 0;
2372}
2373
2374static int out_pause(struct audio_stream_out* stream)
2375{
2376 struct stream_out *out = (struct stream_out *)stream;
2377 int status = -ENOSYS;
2378 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002379 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002380 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 pthread_mutex_lock(&out->lock);
2382 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302383 struct audio_device *adev = out->dev;
2384 int snd_scard_state = get_snd_card_state(adev);
2385
2386 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2387 status = compress_pause(out->compr);
2388
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002390
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302391 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002392 audio_extn_dts_notify_playback_state(out->usecase, 0,
2393 out->sample_rate, popcount(out->channel_mask),
2394 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 }
2396 pthread_mutex_unlock(&out->lock);
2397 }
2398 return status;
2399}
2400
2401static int out_resume(struct audio_stream_out* stream)
2402{
2403 struct stream_out *out = (struct stream_out *)stream;
2404 int status = -ENOSYS;
2405 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002406 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002407 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 status = 0;
2409 pthread_mutex_lock(&out->lock);
2410 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302411 struct audio_device *adev = out->dev;
2412 int snd_scard_state = get_snd_card_state(adev);
2413
2414 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2415 status = compress_resume(out->compr);
2416
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002417 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002418
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302419 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002420 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2421 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 }
2423 pthread_mutex_unlock(&out->lock);
2424 }
2425 return status;
2426}
2427
2428static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2429{
2430 struct stream_out *out = (struct stream_out *)stream;
2431 int status = -ENOSYS;
2432 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002433 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 pthread_mutex_lock(&out->lock);
2435 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2436 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2437 else
2438 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2439 pthread_mutex_unlock(&out->lock);
2440 }
2441 return status;
2442}
2443
2444static int out_flush(struct audio_stream_out* stream)
2445{
2446 struct stream_out *out = (struct stream_out *)stream;
2447 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002448 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002449 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002450 pthread_mutex_lock(&out->lock);
2451 stop_compressed_output_l(out);
2452 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002453 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002454 return 0;
2455 }
2456 return -ENOSYS;
2457}
2458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459/** audio_stream_in implementation **/
2460static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2461{
2462 struct stream_in *in = (struct stream_in *)stream;
2463
2464 return in->config.rate;
2465}
2466
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002467static int in_set_sample_rate(struct audio_stream *stream __unused,
2468 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469{
2470 return -ENOSYS;
2471}
2472
2473static size_t in_get_buffer_size(const struct audio_stream *stream)
2474{
2475 struct stream_in *in = (struct stream_in *)stream;
2476
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2478 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002479 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2480 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002481
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002482 return in->config.period_size *
2483 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484}
2485
2486static uint32_t in_get_channels(const struct audio_stream *stream)
2487{
2488 struct stream_in *in = (struct stream_in *)stream;
2489
2490 return in->channel_mask;
2491}
2492
2493static audio_format_t in_get_format(const struct audio_stream *stream)
2494{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002495 struct stream_in *in = (struct stream_in *)stream;
2496
2497 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498}
2499
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002500static int in_set_format(struct audio_stream *stream __unused,
2501 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502{
2503 return -ENOSYS;
2504}
2505
2506static int in_standby(struct audio_stream *stream)
2507{
2508 struct stream_in *in = (struct stream_in *)stream;
2509 struct audio_device *adev = in->dev;
2510 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302511 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2512 stream, in->usecase, use_case_table[in->usecase]);
2513
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002514 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2515 /* Ignore standby in case of voip call because the voip input
2516 * stream is closed in adev_close_input_stream()
2517 */
2518 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2519 return status;
2520 }
2521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002523 if (!in->standby && in->is_st_session) {
2524 ALOGD("%s: sound trigger pcm stop lab", __func__);
2525 audio_extn_sound_trigger_stop_lab(in);
2526 in->standby = 1;
2527 }
2528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002530 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002532 if (in->pcm) {
2533 pcm_close(in->pcm);
2534 in->pcm = NULL;
2535 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 }
2539 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002540 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 return status;
2542}
2543
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002544static int in_dump(const struct audio_stream *stream __unused,
2545 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546{
2547 return 0;
2548}
2549
2550static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2551{
2552 struct stream_in *in = (struct stream_in *)stream;
2553 struct audio_device *adev = in->dev;
2554 struct str_parms *parms;
2555 char *str;
2556 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002557 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302559 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 parms = str_parms_create_str(kvpairs);
2561
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302562 if (!parms)
2563 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002565 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002566
2567 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2568 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 val = atoi(value);
2570 /* no audio source uses val == 0 */
2571 if ((in->source != val) && (val != 0)) {
2572 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002573 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2574 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2575 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2576 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002577 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002578 err = voice_extn_compress_voip_open_input_stream(in);
2579 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002580 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002581 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002582 }
2583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 }
2585 }
2586
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002587 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2588 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002590 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 in->device = val;
2592 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002593 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002594 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 }
2596 }
2597
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002598done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002600 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601
2602 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302603error:
Eric Laurent994a6932013-07-17 11:51:42 -07002604 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 return ret;
2606}
2607
2608static char* in_get_parameters(const struct audio_stream *stream,
2609 const char *keys)
2610{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002611 struct stream_in *in = (struct stream_in *)stream;
2612 struct str_parms *query = str_parms_create_str(keys);
2613 char *str;
2614 char value[256];
2615 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002616
2617 if (!query || !reply) {
2618 ALOGE("in_get_parameters: failed to create query or reply");
2619 return NULL;
2620 }
2621
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002622 ALOGV("%s: enter: keys - %s", __func__, keys);
2623
2624 voice_extn_in_get_parameters(in, query, reply);
2625
2626 str = str_parms_to_str(reply);
2627 str_parms_destroy(query);
2628 str_parms_destroy(reply);
2629
2630 ALOGV("%s: exit: returns - %s", __func__, str);
2631 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632}
2633
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002634static int in_set_gain(struct audio_stream_in *stream __unused,
2635 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636{
2637 return 0;
2638}
2639
2640static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2641 size_t bytes)
2642{
2643 struct stream_in *in = (struct stream_in *)stream;
2644 struct audio_device *adev = in->dev;
2645 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302646 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302649
2650 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302651 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302652 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302653 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302654 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002655 } else {
2656 if (in->is_st_session && !in->is_st_session_active) {
2657 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2658 ret= -EIO;;
2659 goto exit;
2660 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302661 }
2662 }
2663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002665 if (!in->is_st_session) {
2666 pthread_mutex_lock(&adev->lock);
2667 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2668 ret = voice_extn_compress_voip_start_input_stream(in);
2669 else
2670 ret = start_input_stream(in);
2671 pthread_mutex_unlock(&adev->lock);
2672 if (ret != 0) {
2673 goto exit;
2674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 }
2676 in->standby = 0;
2677 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678
2679 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002680 if (audio_extn_ssr_get_enabled() &&
2681 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002682 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002683 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2684 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002685 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2686 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002687 else
2688 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302689 if (ret < 0)
2690 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 }
2692
2693 /*
2694 * Instead of writing zeroes here, we could trust the hardware
2695 * to always provide zeroes when muted.
2696 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302697 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2698 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 memset(buffer, 0, bytes);
2700
2701exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302702 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302703 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302704 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002705 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2706 session reading on LAB data. In this case do not set sound card state
2707 offline, instead mark this sound trigger session inactive to avoid
2708 further reading of LAB data from CPE driver. Marking the session
2709 inactive handles both CPE and ADSP SSR for sound trigger session */
2710 if (!in->is_st_session)
2711 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2712 else
2713 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 pthread_mutex_unlock(&in->lock);
2716
2717 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302718 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302719 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302720 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302721 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302722 in->standby = true;
2723 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302724 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002726 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002727 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302728 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729 }
2730 return bytes;
2731}
2732
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002733static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
2735 return 0;
2736}
2737
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002738static int add_remove_audio_effect(const struct audio_stream *stream,
2739 effect_handle_t effect,
2740 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002742 struct stream_in *in = (struct stream_in *)stream;
2743 int status = 0;
2744 effect_descriptor_t desc;
2745
2746 status = (*effect)->get_descriptor(effect, &desc);
2747 if (status != 0)
2748 return status;
2749
2750 pthread_mutex_lock(&in->lock);
2751 pthread_mutex_lock(&in->dev->lock);
2752 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2753 in->enable_aec != enable &&
2754 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2755 in->enable_aec = enable;
2756 if (!in->standby)
2757 select_devices(in->dev, in->usecase);
2758 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002759 if (in->enable_ns != enable &&
2760 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2761 in->enable_ns = enable;
2762 if (!in->standby)
2763 select_devices(in->dev, in->usecase);
2764 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002765 pthread_mutex_unlock(&in->dev->lock);
2766 pthread_mutex_unlock(&in->lock);
2767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 return 0;
2769}
2770
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002771static int in_add_audio_effect(const struct audio_stream *stream,
2772 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773{
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, true);
2776}
2777
2778static int in_remove_audio_effect(const struct audio_stream *stream,
2779 effect_handle_t effect)
2780{
Eric Laurent994a6932013-07-17 11:51:42 -07002781 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002782 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783}
2784
2785static int adev_open_output_stream(struct audio_hw_device *dev,
2786 audio_io_handle_t handle,
2787 audio_devices_t devices,
2788 audio_output_flags_t flags,
2789 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002790 struct audio_stream_out **stream_out,
2791 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792{
2793 struct audio_device *adev = (struct audio_device *)dev;
2794 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002795 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002796 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302799
2800 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2801 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2802 ALOGE(" sound card is not active rejecting compress output open request");
2803 return -EINVAL;
2804 }
2805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2807
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302808 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2809 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2810 devices, flags, &out->stream);
2811
2812
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002813 if (!out) {
2814 return -ENOMEM;
2815 }
2816
Haynes Mathew George204045b2015-02-25 20:32:03 -08002817 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2818 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 if (devices == AUDIO_DEVICE_NONE)
2821 devices = AUDIO_DEVICE_OUT_SPEAKER;
2822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 out->flags = flags;
2824 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002825 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002826 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002827 out->sample_rate = config->sample_rate;
2828 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2829 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002830 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002831 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002832 out->non_blocking = 0;
2833 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834
2835 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002836 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2837 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2838 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2839
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002840 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002841 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2842 ret = read_hdmi_channel_masks(out);
2843
2844 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2845 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002846 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002847 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002848 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002849
2850 if (config->sample_rate == 0)
2851 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2852 if (config->channel_mask == 0)
2853 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2854
2855 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2858 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002860 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002862 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2863 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002864 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002865 ret = voice_extn_compress_voip_open_output_stream(out);
2866 if (ret != 0) {
2867 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2868 __func__, ret);
2869 goto error_open;
2870 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2872 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2873 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2874 ALOGE("%s: Unsupported Offload information", __func__);
2875 ret = -EINVAL;
2876 goto error_open;
2877 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002878
2879 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2880 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2881 ALOGV("read and update_pass through formats");
2882 ret = audio_extn_dolby_update_passt_formats(adev, out);
2883 if(ret != 0) {
2884 goto error_open;
2885 }
2886 if(config->offload_info.format == 0)
2887 config->offload_info.format = out->supported_formats[0];
2888 }
2889
Mingming Yin90310102013-11-13 16:57:00 -08002890 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002891 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 ALOGE("%s: Unsupported audio format", __func__);
2893 ret = -EINVAL;
2894 goto error_open;
2895 }
2896
2897 out->compr_config.codec = (struct snd_codec *)
2898 calloc(1, sizeof(struct snd_codec));
2899
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002900 if (!out->compr_config.codec) {
2901 ret = -ENOMEM;
2902 goto error_open;
2903 }
2904
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002905 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 if (config->offload_info.channel_mask)
2907 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002908 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002910 config->offload_info.channel_mask = config->channel_mask;
2911 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002912 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 out->sample_rate = config->offload_info.sample_rate;
2914
2915 out->stream.set_callback = out_set_callback;
2916 out->stream.pause = out_pause;
2917 out->stream.resume = out_resume;
2918 out->stream.drain = out_drain;
2919 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002920 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002922 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002923 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002924 audio_extn_dolby_get_snd_codec_id(adev, out,
2925 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002926 else
2927 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002929 if (audio_is_offload_pcm(config->offload_info.format)) {
2930 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002931 platform_get_pcm_offload_buffer_size(&config->offload_info);
2932 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2933 out->compr_config.fragment_size =
2934 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002935 } else {
2936 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002937 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002938 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2940 out->compr_config.codec->sample_rate =
2941 compress_get_alsa_rate(config->offload_info.sample_rate);
2942 out->compr_config.codec->bit_rate =
2943 config->offload_info.bit_rate;
2944 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002945 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002946 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002947 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002948 /*TODO: Do we need to change it for passthrough */
2949 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950
Mingming Yin3ee55c62014-08-04 14:23:35 -07002951 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2952 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002953 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2954 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002955 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002956 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2957
Mingming Yin3ee55c62014-08-04 14:23:35 -07002958 if (out->bit_width == 24) {
2959 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2960 }
2961
Amit Shekhar6f461b12014-08-01 14:52:58 -07002962 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002963 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002964
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002965 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2966 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002967
Alexy Josephaa54c872014-12-03 02:46:47 -08002968 if (config->offload_info.use_small_bufs) {
2969 //this flag is set from framework only if its for PCM formats
2970 //no need to check for PCM format again
2971 out->non_blocking = 0;
2972 out->use_small_bufs = true;
2973 ALOGI("Keep write blocking for small buff: non_blockling %d",
2974 out->non_blocking);
2975 }
2976
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002977 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002978 out->offload_state = OFFLOAD_STATE_IDLE;
2979 out->playback_started = 0;
2980
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002981 audio_extn_dts_create_state_notifier_node(out->usecase);
2982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 create_offload_callback_thread(out);
2984 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2985 __func__, config->offload_info.version,
2986 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002987 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002988 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002989 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2990 ret = voice_check_and_set_incall_music_usecase(adev, out);
2991 if (ret != 0) {
2992 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2993 __func__, ret);
2994 goto error_open;
2995 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002996 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2997 if (config->sample_rate == 0)
2998 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2999 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3000 config->sample_rate != 8000) {
3001 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3002 ret = -EINVAL;
3003 goto error_open;
3004 }
3005 out->sample_rate = config->sample_rate;
3006 out->config.rate = config->sample_rate;
3007 if (config->format == AUDIO_FORMAT_DEFAULT)
3008 config->format = AUDIO_FORMAT_PCM_16_BIT;
3009 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3010 config->format = AUDIO_FORMAT_PCM_16_BIT;
3011 ret = -EINVAL;
3012 goto error_open;
3013 }
3014 out->format = config->format;
3015 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3016 out->config = pcm_config_afe_proxy_playback;
3017 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003018 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003019 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3021 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07003023 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3024 format = AUDIO_FORMAT_PCM_16_BIT;
3025 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3026 out->config = pcm_config_deep_buffer;
3027 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003028 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003029 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003030 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003031 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07003032 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003033 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 }
3035
Amit Shekhar1d896042014-10-03 13:16:09 -07003036 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3037 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003038 /* TODO remove this hardcoding and check why width is zero*/
3039 if (out->bit_width == 0)
3040 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003041 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3042 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003043 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07003044 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003045 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3046 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3047 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003048 if(adev->primary_output == NULL)
3049 adev->primary_output = out;
3050 else {
3051 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003052 ret = -EEXIST;
3053 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003054 }
3055 }
3056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 /* Check if this usecase is already existing */
3058 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003059 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3060 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003063 ret = -EEXIST;
3064 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 }
3066 pthread_mutex_unlock(&adev->lock);
3067
3068 out->stream.common.get_sample_rate = out_get_sample_rate;
3069 out->stream.common.set_sample_rate = out_set_sample_rate;
3070 out->stream.common.get_buffer_size = out_get_buffer_size;
3071 out->stream.common.get_channels = out_get_channels;
3072 out->stream.common.get_format = out_get_format;
3073 out->stream.common.set_format = out_set_format;
3074 out->stream.common.standby = out_standby;
3075 out->stream.common.dump = out_dump;
3076 out->stream.common.set_parameters = out_set_parameters;
3077 out->stream.common.get_parameters = out_get_parameters;
3078 out->stream.common.add_audio_effect = out_add_audio_effect;
3079 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3080 out->stream.get_latency = out_get_latency;
3081 out->stream.set_volume = out_set_volume;
3082 out->stream.write = out_write;
3083 out->stream.get_render_position = out_get_render_position;
3084 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003085 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003088 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003089 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090
3091 config->format = out->stream.common.get_format(&out->stream.common);
3092 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3093 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3094
3095 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303096 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3097 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003098
3099 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3100 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3101 popcount(out->channel_mask), out->playback_started);
3102
Eric Laurent994a6932013-07-17 11:51:42 -07003103 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003105
3106error_open:
3107 free(out);
3108 *stream_out = NULL;
3109 ALOGD("%s: exit: ret %d", __func__, ret);
3110 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111}
3112
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003113static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 struct audio_stream_out *stream)
3115{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 struct stream_out *out = (struct stream_out *)stream;
3117 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003118 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303120 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3121
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003122 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303123 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003124 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303125 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003126 if(ret != 0)
3127 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3128 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003129 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003130 out_standby(&stream->common);
3131
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003132 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003133 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003135 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003136 if (out->compr_config.codec != NULL)
3137 free(out->compr_config.codec);
3138 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003139
3140 if (adev->voice_tx_output == out)
3141 adev->voice_tx_output = NULL;
3142
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003143 pthread_cond_destroy(&out->cond);
3144 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003146 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147}
3148
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003149static void close_compress_sessions(struct audio_device *adev)
3150{
Mingming Yin7b762e72015-03-04 13:47:32 -08003151 struct stream_out *out;
3152 struct listnode *node;
3153 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003154 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003155 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003156 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003157 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003158 if (usecase && usecase->stream.out) {
3159 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3160 out = usecase->stream.out;
3161 pthread_mutex_unlock(&adev->lock);
3162 out_standby(&out->stream.common);
3163 pthread_mutex_lock(&adev->lock);
3164 }
3165 }
3166 }
3167 pthread_mutex_unlock(&adev->lock);
3168}
3169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3171{
3172 struct audio_device *adev = (struct audio_device *)dev;
3173 struct str_parms *parms;
3174 char *str;
3175 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003176 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003177 int ret;
3178 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003180 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303183 if (!parms)
3184 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003185 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3186 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303187 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303188 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303189 struct listnode *node;
3190 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303191 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303192 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003193 //close compress sessions on OFFLINE status
3194 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303195 } else if (strstr(snd_card_status, "ONLINE")) {
3196 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303197 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303198 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303199 }
3200
3201 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003202 status = voice_set_parameters(adev, parms);
3203 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003204 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003206 status = platform_set_parameters(adev->platform, parms);
3207 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003208 goto done;
3209
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003210 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3211 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003212 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3214 adev->bluetooth_nrec = true;
3215 else
3216 adev->bluetooth_nrec = false;
3217 }
3218
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003219 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3220 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3222 adev->screen_off = false;
3223 else
3224 adev->screen_off = true;
3225 }
3226
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003227 ret = str_parms_get_int(parms, "rotation", &val);
3228 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003229 bool reverse_speakers = false;
3230 switch(val) {
3231 // FIXME: note that the code below assumes that the speakers are in the correct placement
3232 // relative to the user when the device is rotated 90deg from its default rotation. This
3233 // assumption is device-specific, not platform-specific like this code.
3234 case 270:
3235 reverse_speakers = true;
3236 break;
3237 case 0:
3238 case 90:
3239 case 180:
3240 break;
3241 default:
3242 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003243 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003244 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003245 if (status == 0) {
3246 if (adev->speaker_lr_swap != reverse_speakers) {
3247 adev->speaker_lr_swap = reverse_speakers;
3248 // only update the selected device if there is active pcm playback
3249 struct audio_usecase *usecase;
3250 struct listnode *node;
3251 list_for_each(node, &adev->usecase_list) {
3252 usecase = node_to_item(node, struct audio_usecase, list);
3253 if (usecase->type == PCM_PLAYBACK) {
3254 select_devices(adev, usecase->id);
3255 break;
3256 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003257 }
3258 }
3259 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003260 }
3261
Mingming Yin514a8bc2014-07-29 15:22:21 -07003262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3263 if (ret >= 0) {
3264 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3265 adev->bt_wb_speech_enabled = true;
3266 else
3267 adev->bt_wb_speech_enabled = false;
3268 }
3269
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003270 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3271 if (ret >= 0) {
3272 val = atoi(value);
3273 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3274 ALOGV("cache new edid");
3275 platform_cache_edid(adev->platform);
3276 }
3277 }
3278
3279 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3280 if (ret >= 0) {
3281 val = atoi(value);
3282 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3283 ALOGV("invalidate cached edid");
3284 platform_invalidate_edid(adev->platform);
3285 }
3286 }
3287
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003288 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003289
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003290done:
3291 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003292 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303293error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003294 ALOGV("%s: exit with code(%d)", __func__, status);
3295 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296}
3297
3298static char* adev_get_parameters(const struct audio_hw_device *dev,
3299 const char *keys)
3300{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003301 struct audio_device *adev = (struct audio_device *)dev;
3302 struct str_parms *reply = str_parms_create();
3303 struct str_parms *query = str_parms_create_str(keys);
3304 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303305 char value[256] = {0};
3306 int ret = 0;
3307
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003308 if (!query || !reply) {
3309 ALOGE("adev_get_parameters: failed to create query or reply");
3310 return NULL;
3311 }
3312
Naresh Tannirud7205b62014-06-20 02:54:48 +05303313 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3314 sizeof(value));
3315 if (ret >=0) {
3316 int val = 1;
3317 pthread_mutex_lock(&adev->snd_card_status.lock);
3318 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3319 val = 0;
3320 pthread_mutex_unlock(&adev->snd_card_status.lock);
3321 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3322 goto exit;
3323 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003324
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003325 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003326 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003327 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003328 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303329 pthread_mutex_unlock(&adev->lock);
3330
Naresh Tannirud7205b62014-06-20 02:54:48 +05303331exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003332 str = str_parms_to_str(reply);
3333 str_parms_destroy(query);
3334 str_parms_destroy(reply);
3335
3336 ALOGV("%s: exit: returns - %s", __func__, str);
3337 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338}
3339
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003340static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341{
3342 return 0;
3343}
3344
3345static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3346{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003347 int ret;
3348 struct audio_device *adev = (struct audio_device *)dev;
3349 pthread_mutex_lock(&adev->lock);
3350 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003351 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003352 pthread_mutex_unlock(&adev->lock);
3353 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354}
3355
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003356static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3357 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358{
3359 return -ENOSYS;
3360}
3361
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003362static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3363 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364{
3365 return -ENOSYS;
3366}
3367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003368static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3369 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370{
3371 return -ENOSYS;
3372}
3373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003374static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3375 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376{
3377 return -ENOSYS;
3378}
3379
3380static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3381{
3382 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 pthread_mutex_lock(&adev->lock);
3385 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003386 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003388 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3389 voice_is_in_call(adev)) {
3390 voice_stop_call(adev);
3391 adev->current_call_output = NULL;
3392 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 }
3394 pthread_mutex_unlock(&adev->lock);
3395 return 0;
3396}
3397
3398static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3399{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003400 int ret;
3401
3402 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003403 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003404 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3405 pthread_mutex_unlock(&adev->lock);
3406
3407 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408}
3409
3410static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3411{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003412 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 return 0;
3414}
3415
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003416static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 const struct audio_config *config)
3418{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003419 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003421 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3422 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423}
3424
3425static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003426 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 audio_devices_t devices,
3428 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003429 struct audio_stream_in **stream_in,
3430 audio_input_flags_t flags __unused,
3431 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003432 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433{
3434 struct audio_device *adev = (struct audio_device *)dev;
3435 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003436 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003437 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003438 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 *stream_in = NULL;
3441 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3442 return -EINVAL;
3443
3444 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003445
3446 if (!in) {
3447 ALOGE("failed to allocate input stream");
3448 return -ENOMEM;
3449 }
3450
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303451 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003452 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3453 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003455 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 in->stream.common.get_sample_rate = in_get_sample_rate;
3458 in->stream.common.set_sample_rate = in_set_sample_rate;
3459 in->stream.common.get_buffer_size = in_get_buffer_size;
3460 in->stream.common.get_channels = in_get_channels;
3461 in->stream.common.get_format = in_get_format;
3462 in->stream.common.set_format = in_set_format;
3463 in->stream.common.standby = in_standby;
3464 in->stream.common.dump = in_dump;
3465 in->stream.common.set_parameters = in_set_parameters;
3466 in->stream.common.get_parameters = in_get_parameters;
3467 in->stream.common.add_audio_effect = in_add_audio_effect;
3468 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3469 in->stream.set_gain = in_set_gain;
3470 in->stream.read = in_read;
3471 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3472
3473 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003474 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476 in->standby = 1;
3477 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003478 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479
3480 /* Update config params with the requested sample rate and channels */
3481 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003482 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3483 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3484 is_low_latency = true;
3485#if LOW_LATENCY_CAPTURE_USE_CASE
3486 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3487#endif
3488 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003491 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003493 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303494 if (adev->mode != AUDIO_MODE_IN_CALL) {
3495 ret = -EINVAL;
3496 goto err_open;
3497 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003498 if (config->sample_rate == 0)
3499 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3500 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3501 config->sample_rate != 8000) {
3502 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3503 ret = -EINVAL;
3504 goto err_open;
3505 }
3506 if (config->format == AUDIO_FORMAT_DEFAULT)
3507 config->format = AUDIO_FORMAT_PCM_16_BIT;
3508 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3509 config->format = AUDIO_FORMAT_PCM_16_BIT;
3510 ret = -EINVAL;
3511 goto err_open;
3512 }
3513
3514 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3515 in->config = pcm_config_afe_proxy_record;
3516 in->config.channels = channel_count;
3517 in->config.rate = config->sample_rate;
3518 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003519 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003520 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003521 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3522 ret = -EINVAL;
3523 goto err_open;
3524 }
3525 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003526 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003527 }
Mingming Yine62d7842013-10-25 16:26:03 -07003528 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003529 audio_extn_compr_cap_format_supported(config->format) &&
3530 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003531 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003532 } else {
3533 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003534 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003535 buffer_size = get_input_buffer_size(config->sample_rate,
3536 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003537 channel_count,
3538 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003539 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003540 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3541 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3542 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3543 (in->config.rate == 8000 || in->config.rate == 16000) &&
3544 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3545 voice_extn_compress_voip_open_input_stream(in);
3546 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003549 /* This stream could be for sound trigger lab,
3550 get sound trigger pcm if present */
3551 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303552 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003555 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003556 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557
3558err_open:
3559 free(in);
3560 *stream_in = NULL;
3561 return ret;
3562}
3563
3564static void adev_close_input_stream(struct audio_hw_device *dev,
3565 struct audio_stream_in *stream)
3566{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003567 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003568 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003569 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303570
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303571 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003572
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303573 /* Disable echo reference while closing input stream */
3574 platform_set_echo_reference(adev->platform, false);
3575
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003576 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303577 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003578 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303579 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003580 if (ret != 0)
3581 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3582 __func__, ret);
3583 } else
3584 in_standby(&stream->common);
3585
Mingming Yin7b762e72015-03-04 13:47:32 -08003586 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003587 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003588 audio_extn_ssr_deinit();
3589 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590
Mingming Yine62d7842013-10-25 16:26:03 -07003591 if(audio_extn_compr_cap_enabled() &&
3592 audio_extn_compr_cap_format_supported(in->config.format))
3593 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003594
3595 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 return;
3597}
3598
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003599static int adev_dump(const audio_hw_device_t *device __unused,
3600 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601{
3602 return 0;
3603}
3604
3605static int adev_close(hw_device_t *device)
3606{
3607 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003608
3609 if (!adev)
3610 return 0;
3611
3612 pthread_mutex_lock(&adev_init_lock);
3613
3614 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003615 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003616 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003617 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003618 audio_route_free(adev->audio_route);
3619 free(adev->snd_dev_ref_cnt);
3620 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003621 free(device);
3622 adev = NULL;
3623 }
3624 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003625 return 0;
3626}
3627
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003628/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3629 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3630 * just that it _might_ work.
3631 */
3632static int period_size_is_plausible_for_low_latency(int period_size)
3633{
3634 switch (period_size) {
3635 case 160:
3636 case 240:
3637 case 320:
3638 case 480:
3639 return 1;
3640 default:
3641 return 0;
3642 }
3643}
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645static int adev_open(const hw_module_t *module, const char *name,
3646 hw_device_t **device)
3647{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003648 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003650 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3652
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003653 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003654 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003655 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003656 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003657 ALOGD("%s: returning existing instance of adev", __func__);
3658 ALOGD("%s: exit", __func__);
3659 pthread_mutex_unlock(&adev_init_lock);
3660 return 0;
3661 }
3662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 adev = calloc(1, sizeof(struct audio_device));
3664
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003665 if (!adev) {
3666 pthread_mutex_unlock(&adev_init_lock);
3667 return -ENOMEM;
3668 }
3669
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003670 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3673 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3674 adev->device.common.module = (struct hw_module_t *)module;
3675 adev->device.common.close = adev_close;
3676
3677 adev->device.init_check = adev_init_check;
3678 adev->device.set_voice_volume = adev_set_voice_volume;
3679 adev->device.set_master_volume = adev_set_master_volume;
3680 adev->device.get_master_volume = adev_get_master_volume;
3681 adev->device.set_master_mute = adev_set_master_mute;
3682 adev->device.get_master_mute = adev_get_master_mute;
3683 adev->device.set_mode = adev_set_mode;
3684 adev->device.set_mic_mute = adev_set_mic_mute;
3685 adev->device.get_mic_mute = adev_get_mic_mute;
3686 adev->device.set_parameters = adev_set_parameters;
3687 adev->device.get_parameters = adev_get_parameters;
3688 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3689 adev->device.open_output_stream = adev_open_output_stream;
3690 adev->device.close_output_stream = adev_close_output_stream;
3691 adev->device.open_input_stream = adev_open_input_stream;
3692 adev->device.close_input_stream = adev_close_input_stream;
3693 adev->device.dump = adev_dump;
3694
3695 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003697 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003698 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003701 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003702 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003703 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3704 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003705 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003706 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003707 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003708 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003709 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303710
3711 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3712 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003714 adev->platform = platform_init(adev);
3715 if (!adev->platform) {
3716 free(adev->snd_dev_ref_cnt);
3717 free(adev);
3718 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3719 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003720 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003721 return -EINVAL;
3722 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003723
Naresh Tanniru4c630392014-05-12 01:05:52 +05303724 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3725
Eric Laurentc4aef752013-09-12 17:45:53 -07003726 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3727 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3728 if (adev->visualizer_lib == NULL) {
3729 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3730 } else {
3731 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3732 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003733 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003734 "visualizer_hal_start_output");
3735 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003736 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003737 "visualizer_hal_stop_output");
3738 }
3739 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003740 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003741 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003742
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003743 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3744 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3745 if (adev->offload_effects_lib == NULL) {
3746 ALOGE("%s: DLOPEN failed for %s", __func__,
3747 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3748 } else {
3749 ALOGV("%s: DLOPEN successful for %s", __func__,
3750 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3751 adev->offload_effects_start_output =
3752 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3753 "offload_effects_bundle_hal_start_output");
3754 adev->offload_effects_stop_output =
3755 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3756 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003757 adev->offload_effects_set_hpx_state =
3758 (int (*)(bool))dlsym(adev->offload_effects_lib,
3759 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003760 }
3761 }
3762
Mingming Yin514a8bc2014-07-29 15:22:21 -07003763 adev->bt_wb_speech_enabled = false;
3764
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003765 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 *device = &adev->device.common;
3767
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003768 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3769 &adev->streams_output_cfg_list);
3770
Kiran Kandi910e1862013-10-29 13:29:42 -07003771 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003772
3773 char value[PROPERTY_VALUE_MAX];
3774 int trial;
3775 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3776 trial = atoi(value);
3777 if (period_size_is_plausible_for_low_latency(trial)) {
3778 pcm_config_low_latency.period_size = trial;
3779 pcm_config_low_latency.start_threshold = trial / 4;
3780 pcm_config_low_latency.avail_min = trial / 4;
3781 configured_low_latency_capture_period_size = trial;
3782 }
3783 }
3784 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3785 trial = atoi(value);
3786 if (period_size_is_plausible_for_low_latency(trial)) {
3787 configured_low_latency_capture_period_size = trial;
3788 }
3789 }
3790
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003791 pthread_mutex_unlock(&adev_init_lock);
3792
Eric Laurent994a6932013-07-17 11:51:42 -07003793 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 return 0;
3795}
3796
3797static struct hw_module_methods_t hal_module_methods = {
3798 .open = adev_open,
3799};
3800
3801struct audio_module HAL_MODULE_INFO_SYM = {
3802 .common = {
3803 .tag = HARDWARE_MODULE_TAG,
3804 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3805 .hal_api_version = HARDWARE_HAL_API_VERSION,
3806 .id = AUDIO_HARDWARE_MODULE_ID,
3807 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003808 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 .methods = &hal_module_methods,
3810 },
3811};