blob: 097583b6d75a1609b8600b382f7e736853a26a72 [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
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080084#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
85
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070086static unsigned int configured_low_latency_capture_period_size =
87 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
88
Eric Laurentb23d5282013-05-14 15:27:20 -070089struct pcm_config pcm_config_deep_buffer = {
90 .channels = 2,
91 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
92 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
93 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
94 .format = PCM_FORMAT_S16_LE,
95 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
96 .stop_threshold = INT_MAX,
97 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
98};
99
100struct pcm_config pcm_config_low_latency = {
101 .channels = 2,
102 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
103 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
104 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
105 .format = PCM_FORMAT_S16_LE,
106 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
107 .stop_threshold = INT_MAX,
108 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
109};
110
111struct pcm_config pcm_config_hdmi_multi = {
112 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
113 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
114 .period_size = HDMI_MULTI_PERIOD_SIZE,
115 .period_count = HDMI_MULTI_PERIOD_COUNT,
116 .format = PCM_FORMAT_S16_LE,
117 .start_threshold = 0,
118 .stop_threshold = INT_MAX,
119 .avail_min = 0,
120};
121
122struct pcm_config pcm_config_audio_capture = {
123 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700124 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
125 .format = PCM_FORMAT_S16_LE,
126};
127
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700128#define AFE_PROXY_CHANNEL_COUNT 2
129#define AFE_PROXY_SAMPLING_RATE 48000
130
131#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
132#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
133
134struct pcm_config pcm_config_afe_proxy_playback = {
135 .channels = AFE_PROXY_CHANNEL_COUNT,
136 .rate = AFE_PROXY_SAMPLING_RATE,
137 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
138 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
139 .format = PCM_FORMAT_S16_LE,
140 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
141 .stop_threshold = INT_MAX,
142 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
143};
144
145#define AFE_PROXY_RECORD_PERIOD_SIZE 768
146#define AFE_PROXY_RECORD_PERIOD_COUNT 4
147
148struct pcm_config pcm_config_afe_proxy_record = {
149 .channels = AFE_PROXY_CHANNEL_COUNT,
150 .rate = AFE_PROXY_SAMPLING_RATE,
151 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
152 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
155 .stop_threshold = INT_MAX,
156 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
157};
158
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800159const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700160 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
161 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
162 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700163 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700164#ifdef MULTIPLE_OFFLOAD_ENABLED
165 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
166 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
167 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
168 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
169 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
170 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
173#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700174 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700175 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700176 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700177 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700178 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800179 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800180 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700181 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700182
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700183 [USECASE_VOICE2_CALL] = "voice2-call",
184 [USECASE_VOLTE_CALL] = "volte-call",
185 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800186 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800187 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700188 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
189 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
190 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800191 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
192 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
193 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
194
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700195 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
196 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700197 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
198 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700199
200 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
201 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700202};
203
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700204static const audio_usecase_t offload_usecases[] = {
205 USECASE_AUDIO_PLAYBACK_OFFLOAD,
206#ifdef MULTIPLE_OFFLOAD_ENABLED
207 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
208 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
209 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
210 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
211 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
212 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
213 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
214 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
215#endif
216};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800217
218#define STRING_TO_ENUM(string) { #string, string }
219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800220struct string_to_enum {
221 const char *name;
222 uint32_t value;
223};
224
225static const struct string_to_enum out_channels_name_to_enum_table[] = {
226 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
230 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
231 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800232 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
233};
234
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700235static const struct string_to_enum out_formats_name_to_enum_table[] = {
236 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
237 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
238 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
239};
240
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700241static struct audio_device *adev = NULL;
242static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700243static unsigned int audio_device_ref_count;
244
Haynes Mathew George5191a852013-09-11 14:19:36 -0700245static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800246
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800247static int check_and_set_gapless_mode(struct audio_device *adev) {
248
249
250 char value[PROPERTY_VALUE_MAX] = {0};
251 bool gapless_enabled = false;
252 const char *mixer_ctl_name = "Compress Gapless Playback";
253 struct mixer_ctl *ctl;
254
255 ALOGV("%s:", __func__);
256 property_get("audio.offload.gapless.enabled", value, NULL);
257 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
258
259 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
260 if (!ctl) {
261 ALOGE("%s: Could not get ctl for mixer cmd - %s",
262 __func__, mixer_ctl_name);
263 return -EINVAL;
264 }
265
266 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
267 ALOGE("%s: Could not set gapless mode %d",
268 __func__, gapless_enabled);
269 return -EINVAL;
270 }
271 return 0;
272}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700273
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700274static bool is_supported_format(audio_format_t format)
275{
Eric Laurent86e17132013-09-12 17:49:30 -0700276 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530277 format == AUDIO_FORMAT_AAC_LC ||
278 format == AUDIO_FORMAT_AAC_HE_V1 ||
279 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800280 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700281 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
282 format == AUDIO_FORMAT_FLAC)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800283 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700284
285 return false;
286}
287
288static int get_snd_codec_id(audio_format_t format)
289{
290 int id = 0;
291
Ashish Jainf9b78162014-08-25 20:36:25 +0530292 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700293 case AUDIO_FORMAT_MP3:
294 id = SND_AUDIOCODEC_MP3;
295 break;
296 case AUDIO_FORMAT_AAC:
297 id = SND_AUDIOCODEC_AAC;
298 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530299 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800300 id = SND_AUDIOCODEC_PCM;
301 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700302 case AUDIO_FORMAT_FLAC:
303 id = SND_AUDIOCODEC_FLAC;
304 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700305 default:
Mingming Yin90310102013-11-13 16:57:00 -0800306 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700307 }
308
309 return id;
310}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800311
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530312int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530313{
314 int snd_scard_state;
315
316 if (!adev)
317 return SND_CARD_STATE_OFFLINE;
318
319 pthread_mutex_lock(&adev->snd_card_status.lock);
320 snd_scard_state = adev->snd_card_status.state;
321 pthread_mutex_unlock(&adev->snd_card_status.lock);
322
323 return snd_scard_state;
324}
325
326static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
327{
328 if (!adev)
329 return -ENOSYS;
330
331 pthread_mutex_lock(&adev->snd_card_status.lock);
332 adev->snd_card_status.state = snd_scard_state;
333 pthread_mutex_unlock(&adev->snd_card_status.lock);
334
335 return 0;
336}
337
Avinash Vaish71a8b972014-07-24 15:36:33 +0530338static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
339 struct audio_usecase *uc_info)
340{
341 struct listnode *node;
342 struct audio_usecase *usecase;
343
344 if (uc_info == NULL)
345 return -EINVAL;
346
347 /* Re-route all voice usecases on the shared backend other than the
348 specified usecase to new snd devices */
349 list_for_each(node, &adev->usecase_list) {
350 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800351 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530352 enable_audio_route(adev, usecase);
353 }
354 return 0;
355}
356
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700357int pcm_ioctl(struct pcm *pcm, int request, ...)
358{
359 va_list ap;
360 void * arg;
361 int pcm_fd = *(int*)pcm;
362
363 va_start(ap, request);
364 arg = va_arg(ap, void *);
365 va_end(ap);
366
367 return ioctl(pcm_fd, request, arg);
368}
369
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700370int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700371 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800372{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700373 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700374 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800375
376 if (usecase == NULL)
377 return -EINVAL;
378
379 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
380
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800381 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700382 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800383 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700384 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800385
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800386#ifdef DS1_DOLBY_DAP_ENABLED
387 audio_extn_dolby_set_dmid(adev);
388 audio_extn_dolby_set_endpoint(adev);
389#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700390 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700391 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530392 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700393 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700394 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800395 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700396 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700397 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
398 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800399 ALOGV("%s: exit", __func__);
400 return 0;
401}
402
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700403int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700404 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800405{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700406 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700407 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800408
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530409 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800410 return -EINVAL;
411
412 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700413 if (usecase->type == PCM_CAPTURE)
414 snd_device = usecase->in_snd_device;
415 else
416 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800417 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700418 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700419 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
420 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700421 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530422 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423 ALOGV("%s: exit", __func__);
424 return 0;
425}
426
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700427int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700428 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700430 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
431
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800432 if (snd_device < SND_DEVICE_MIN ||
433 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800434 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800435 return -EINVAL;
436 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700437
438 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700439
440 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
441 ALOGE("%s: Invalid sound device returned", __func__);
442 return -EINVAL;
443 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700444 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700445 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700446 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447 return 0;
448 }
449
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700450 if (audio_extn_spkr_prot_is_enabled())
451 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700452 /* start usb playback thread */
453 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
454 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
455 audio_extn_usb_start_playback(adev);
456
457 /* start usb capture thread */
458 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
459 audio_extn_usb_start_capture(adev);
460
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800461 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
462 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700463 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700464 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
465 adev->snd_dev_ref_cnt[snd_device]--;
466 return -EINVAL;
467 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200468 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800469 if (audio_extn_spkr_prot_start_processing(snd_device)) {
470 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200471 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800472 return -EINVAL;
473 }
474 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700475 ALOGV("%s: snd_device(%d: %s)", __func__,
476 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700477 /* due to the possibility of calibration overwrite between listen
478 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700479 audio_extn_sound_trigger_update_device_status(snd_device,
480 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530481 audio_extn_listen_update_device_status(snd_device,
482 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700483 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700484 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700485 audio_extn_sound_trigger_update_device_status(snd_device,
486 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530487 audio_extn_listen_update_device_status(snd_device,
488 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700489 return -EINVAL;
490 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300491 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700492 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800494 return 0;
495}
496
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700497int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700498 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800499{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700500 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
501
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800502 if (snd_device < SND_DEVICE_MIN ||
503 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800504 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800505 return -EINVAL;
506 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700507 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
508 ALOGE("%s: device ref cnt is already 0", __func__);
509 return -EINVAL;
510 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700511
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700513
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700514 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
515 ALOGE("%s: Invalid sound device returned", __func__);
516 return -EINVAL;
517 }
518
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700519 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700520 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700521 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800522 /* exit usb play back thread */
523 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
524 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
525 audio_extn_usb_stop_playback();
526
527 /* exit usb capture thread */
528 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700529 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800530
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800531 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
532 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700533 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700534 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300535 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700536 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300537 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700538
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200539 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700540 audio_extn_sound_trigger_update_device_status(snd_device,
541 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530542 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800543 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700544 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800546 return 0;
547}
548
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700549static void check_usecases_codec_backend(struct audio_device *adev,
550 struct audio_usecase *uc_info,
551 snd_device_t snd_device)
552{
553 struct listnode *node;
554 struct audio_usecase *usecase;
555 bool switch_device[AUDIO_USECASE_MAX];
556 int i, num_uc_to_switch = 0;
557
558 /*
559 * This function is to make sure that all the usecases that are active on
560 * the hardware codec backend are always routed to any one device that is
561 * handled by the hardware codec.
562 * For example, if low-latency and deep-buffer usecases are currently active
563 * on speaker and out_set_parameters(headset) is received on low-latency
564 * output, then we have to make sure deep-buffer is also switched to headset,
565 * because of the limitation that both the devices cannot be enabled
566 * at the same time as they share the same backend.
567 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700568 /*
569 * This call is to check if we need to force routing for a particular stream
570 * If there is a backend configuration change for the device when a
571 * new stream starts, then ADM needs to be closed and re-opened with the new
572 * configuraion. This call check if we need to re-route all the streams
573 * associated with the backend. Touch tone + 24 bit playback.
574 */
575 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 /* Disable all the usecases on the shared backend other than the
578 specified usecase */
579 for (i = 0; i < AUDIO_USECASE_MAX; i++)
580 switch_device[i] = false;
581
582 list_for_each(node, &adev->usecase_list) {
583 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800584 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700586 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
588 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
589 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700590 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700591 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592 switch_device[usecase->id] = true;
593 num_uc_to_switch++;
594 }
595 }
596
597 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700598 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700599
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530600 /* Make sure the previous devices to be disabled first and then enable the
601 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700602 list_for_each(node, &adev->usecase_list) {
603 usecase = node_to_item(node, struct audio_usecase, list);
604 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700605 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700606 }
607 }
608
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700609 list_for_each(node, &adev->usecase_list) {
610 usecase = node_to_item(node, struct audio_usecase, list);
611 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700612 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700613 }
614 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 /* Re-route all the usecases on the shared backend other than the
617 specified usecase to new snd devices */
618 list_for_each(node, &adev->usecase_list) {
619 usecase = node_to_item(node, struct audio_usecase, list);
620 /* Update the out_snd_device only before enabling the audio route */
621 if (switch_device[usecase->id] ) {
622 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800623 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530624 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625 }
626 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700627 }
628}
629
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700630static void check_and_route_capture_usecases(struct audio_device *adev,
631 struct audio_usecase *uc_info,
632 snd_device_t snd_device)
633{
634 struct listnode *node;
635 struct audio_usecase *usecase;
636 bool switch_device[AUDIO_USECASE_MAX];
637 int i, num_uc_to_switch = 0;
638
639 /*
640 * This function is to make sure that all the active capture usecases
641 * are always routed to the same input sound device.
642 * For example, if audio-record and voice-call usecases are currently
643 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
644 * is received for voice call then we have to make sure that audio-record
645 * usecase is also switched to earpiece i.e. voice-dmic-ef,
646 * because of the limitation that two devices cannot be enabled
647 * at the same time if they share the same backend.
648 */
649 for (i = 0; i < AUDIO_USECASE_MAX; i++)
650 switch_device[i] = false;
651
652 list_for_each(node, &adev->usecase_list) {
653 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800654 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700655 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700656 usecase->in_snd_device != snd_device &&
657 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700658 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
659 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700660 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700661 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700662 switch_device[usecase->id] = true;
663 num_uc_to_switch++;
664 }
665 }
666
667 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700668 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700669
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530670 /* Make sure the previous devices to be disabled first and then enable the
671 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700672 list_for_each(node, &adev->usecase_list) {
673 usecase = node_to_item(node, struct audio_usecase, list);
674 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700675 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800676 }
677 }
678
679 list_for_each(node, &adev->usecase_list) {
680 usecase = node_to_item(node, struct audio_usecase, list);
681 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700682 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700683 }
684 }
685
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700686 /* Re-route all the usecases on the shared backend other than the
687 specified usecase to new snd devices */
688 list_for_each(node, &adev->usecase_list) {
689 usecase = node_to_item(node, struct audio_usecase, list);
690 /* Update the in_snd_device only before enabling the audio route */
691 if (switch_device[usecase->id] ) {
692 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800693 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530694 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 }
696 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700697 }
698}
699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700701static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800702{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700703 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700704 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800705
706 switch (channels) {
707 /*
708 * Do not handle stereo output in Multi-channel cases
709 * Stereo case is handled in normal playback path
710 */
711 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700712 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
713 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
714 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
715 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
716 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
717 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800718 break;
719 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700720 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
721 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
722 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
723 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
724 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
725 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
726 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727 break;
728 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700729 ALOGE("HDMI does not support multi channel playback");
730 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800731 break;
732 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700733 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800734}
735
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700736static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
737{
738 struct audio_usecase *usecase;
739 struct listnode *node;
740
741 list_for_each(node, &adev->usecase_list) {
742 usecase = node_to_item(node, struct audio_usecase, list);
743 if (usecase->type == VOICE_CALL) {
744 ALOGV("%s: usecase id %d", __func__, usecase->id);
745 return usecase->id;
746 }
747 }
748 return USECASE_INVALID;
749}
750
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700751struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700752 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753{
754 struct audio_usecase *usecase;
755 struct listnode *node;
756
757 list_for_each(node, &adev->usecase_list) {
758 usecase = node_to_item(node, struct audio_usecase, list);
759 if (usecase->id == uc_id)
760 return usecase;
761 }
762 return NULL;
763}
764
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700765int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800766{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800767 snd_device_t out_snd_device = SND_DEVICE_NONE;
768 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700769 struct audio_usecase *usecase = NULL;
770 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800771 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800772 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800773 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800774 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700775 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 usecase = get_usecase_from_list(adev, uc_id);
778 if (usecase == NULL) {
779 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
780 return -EINVAL;
781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800783 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800784 (usecase->type == VOIP_CALL) ||
785 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700786 out_snd_device = platform_get_output_snd_device(adev->platform,
787 usecase->stream.out->devices);
788 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 usecase->devices = usecase->stream.out->devices;
790 } else {
791 /*
792 * If the voice call is active, use the sound devices of voice call usecase
793 * so that it would not result any device switch. All the usecases will
794 * be switched to new device when select_devices() is called for voice call
795 * usecase. This is to avoid switching devices for voice call when
796 * check_usecases_codec_backend() is called below.
797 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700798 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700799 vc_usecase = get_usecase_from_list(adev,
800 get_voice_usecase_id_from_list(adev));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700801 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
802 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700803 in_snd_device = vc_usecase->in_snd_device;
804 out_snd_device = vc_usecase->out_snd_device;
805 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800806 } else if (voice_extn_compress_voip_is_active(adev)) {
807 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700808 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530809 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700810 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800811 in_snd_device = voip_usecase->in_snd_device;
812 out_snd_device = voip_usecase->out_snd_device;
813 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800814 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800815 hfp_ucid = audio_extn_hfp_get_usecase();
816 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700817 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800818 in_snd_device = hfp_usecase->in_snd_device;
819 out_snd_device = hfp_usecase->out_snd_device;
820 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821 }
822 if (usecase->type == PCM_PLAYBACK) {
823 usecase->devices = usecase->stream.out->devices;
824 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700825 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700826 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700828 if (usecase->stream.out == adev->primary_output &&
829 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800830 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
831 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700832 select_devices(adev, adev->active_input->usecase);
833 }
834 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 } else if (usecase->type == PCM_CAPTURE) {
836 usecase->devices = usecase->stream.in->device;
837 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700838 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700839 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530840 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
841 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
842 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
843 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700844 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800845 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700846 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
847 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700848 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700849 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 }
852 }
853
854 if (out_snd_device == usecase->out_snd_device &&
855 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800856 return 0;
857 }
858
sangwoobc677242013-08-08 16:53:43 +0900859 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700860 out_snd_device, platform_get_snd_device_name(out_snd_device),
861 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863 /*
864 * Limitation: While in call, to do a device switch we need to disable
865 * and enable both RX and TX devices though one of them is same as current
866 * device.
867 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700868 if ((usecase->type == VOICE_CALL) &&
869 (usecase->in_snd_device != SND_DEVICE_NONE) &&
870 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700871 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800872 }
873
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 /* Disable current sound devices */
875 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700876 disable_audio_route(adev, usecase);
877 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878 }
879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700881 disable_audio_route(adev, usecase);
882 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800883 }
884
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800885 /* Applicable only on the targets that has external modem.
886 * New device information should be sent to modem before enabling
887 * the devices to reduce in-call device switch time.
888 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700889 if ((usecase->type == VOICE_CALL) &&
890 (usecase->in_snd_device != SND_DEVICE_NONE) &&
891 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800892 status = platform_switch_voice_call_enable_device_config(adev->platform,
893 out_snd_device,
894 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700895 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800896
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 /* Enable new sound devices */
898 if (out_snd_device != SND_DEVICE_NONE) {
899 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
900 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700901 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800902 }
903
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700904 if (in_snd_device != SND_DEVICE_NONE) {
905 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700906 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700907 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908
Avinash Vaish71a8b972014-07-24 15:36:33 +0530909 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700910 status = platform_switch_voice_call_device_post(adev->platform,
911 out_snd_device,
912 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530913 enable_audio_route_for_voice_usecases(adev, usecase);
914 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800915
sangwoo170731f2013-06-08 15:36:36 +0900916 usecase->in_snd_device = in_snd_device;
917 usecase->out_snd_device = out_snd_device;
918
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530919 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700920 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530921 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700922 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530923 usecase->stream.out->flags,
924 usecase->stream.out->format,
925 usecase->stream.out->sample_rate,
926 usecase->stream.out->bit_width,
927 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700928 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530929 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700930
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700931 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900932
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800933 /* Applicable only on the targets that has external modem.
934 * Enable device command should be sent to modem only after
935 * enabling voice call mixer controls
936 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700937 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800938 status = platform_switch_voice_call_usecase_route_post(adev->platform,
939 out_snd_device,
940 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530941 ALOGD("%s: done",__func__);
942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800943 return status;
944}
945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946static int stop_input_stream(struct stream_in *in)
947{
948 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800949 struct audio_usecase *uc_info;
950 struct audio_device *adev = in->dev;
951
Eric Laurentc8400632013-02-14 19:04:54 -0800952 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953
Eric Laurent994a6932013-07-17 11:51:42 -0700954 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700955 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956 uc_info = get_usecase_from_list(adev, in->usecase);
957 if (uc_info == NULL) {
958 ALOGE("%s: Could not find the usecase (%d) in the list",
959 __func__, in->usecase);
960 return -EINVAL;
961 }
962
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800963 /* Close in-call recording streams */
964 voice_check_and_stop_incall_rec_usecase(adev, in);
965
Eric Laurent150dbfe2013-02-27 14:31:02 -0800966 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700967 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968
969 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700970 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800972 list_remove(&uc_info->list);
973 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974
Eric Laurent994a6932013-07-17 11:51:42 -0700975 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976 return ret;
977}
978
979int start_input_stream(struct stream_in *in)
980{
981 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800982 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983 struct audio_usecase *uc_info;
984 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530985 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986
Mingming Yine62d7842013-10-25 16:26:03 -0700987 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530988 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
989 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700990
Naresh Tanniru80659832014-06-04 18:17:56 +0530991
992 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +0530993 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +0530994 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +0530995 goto error_config;
996 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530997
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700998 /* Check if source matches incall recording usecase criteria */
999 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1000 if (ret)
1001 goto error_config;
1002 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001003 ALOGD("%s: Updated usecase(%d: %s)",
1004 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001005
Eric Laurentb23d5282013-05-14 15:27:20 -07001006 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 if (in->pcm_device_id < 0) {
1008 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1009 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001010 ret = -EINVAL;
1011 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001012 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013
1014 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001016
1017 if (!uc_info) {
1018 ret = -ENOMEM;
1019 goto error_config;
1020 }
1021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022 uc_info->id = in->usecase;
1023 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001024 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001025 uc_info->devices = in->device;
1026 uc_info->in_snd_device = SND_DEVICE_NONE;
1027 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001029 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301030 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032
Eric Laurentc8400632013-02-14 19:04:54 -08001033 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001034 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1035
1036 unsigned int flags = PCM_IN;
1037 unsigned int pcm_open_retry_count = 0;
1038
1039 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1040 flags |= PCM_MMAP | PCM_NOIRQ;
1041 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1042 }
1043
1044 while (1) {
1045 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1046 flags, &in->config);
1047 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1048 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1049 if (in->pcm != NULL) {
1050 pcm_close(in->pcm);
1051 in->pcm = NULL;
1052 }
1053 if (pcm_open_retry_count-- == 0) {
1054 ret = -EIO;
1055 goto error_open;
1056 }
1057 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1058 continue;
1059 }
1060 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301062 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301063
Eric Laurent994a6932013-07-17 11:51:42 -07001064 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001065 return ret;
1066
1067error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301069 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001070
1071error_config:
1072 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001074
1075 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076}
1077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001078/* must be called with out->lock locked */
1079static int send_offload_cmd_l(struct stream_out* out, int command)
1080{
1081 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1082
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001083 if (!cmd) {
1084 ALOGE("failed to allocate mem for command 0x%x", command);
1085 return -ENOMEM;
1086 }
1087
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001088 ALOGVV("%s %d", __func__, command);
1089
1090 cmd->cmd = command;
1091 list_add_tail(&out->offload_cmd_list, &cmd->node);
1092 pthread_cond_signal(&out->offload_cond);
1093 return 0;
1094}
1095
1096/* must be called iwth out->lock locked */
1097static void stop_compressed_output_l(struct stream_out *out)
1098{
1099 out->offload_state = OFFLOAD_STATE_IDLE;
1100 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001101 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001102 if (out->compr != NULL) {
1103 compress_stop(out->compr);
1104 while (out->offload_thread_blocked) {
1105 pthread_cond_wait(&out->cond, &out->lock);
1106 }
1107 }
1108}
1109
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001110bool is_offload_usecase(audio_usecase_t uc_id)
1111{
1112 unsigned int i;
1113 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1114 if (uc_id == offload_usecases[i])
1115 return true;
1116 }
1117 return false;
1118}
1119
1120static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1121{
1122 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1123 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1124 char value[PROPERTY_VALUE_MAX] = {0};
1125
1126 property_get("audio.offload.multiple.enabled", value, NULL);
1127 if (!(atoi(value) || !strncmp("true", value, 4)))
1128 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1129
1130 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1131 for (i = 0; i < num_usecase; i++) {
1132 if (!(adev->offload_usecases_state & (0x1<<i))) {
1133 adev->offload_usecases_state |= 0x1 << i;
1134 ret = offload_usecases[i];
1135 break;
1136 }
1137 }
1138 ALOGV("%s: offload usecase is %d", __func__, ret);
1139 return ret;
1140}
1141
1142static void free_offload_usecase(struct audio_device *adev,
1143 audio_usecase_t uc_id)
1144{
1145 unsigned int i;
1146 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1147 if (offload_usecases[i] == uc_id) {
1148 adev->offload_usecases_state &= ~(0x1<<i);
1149 break;
1150 }
1151 }
1152 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1153}
1154
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001155static void *offload_thread_loop(void *context)
1156{
1157 struct stream_out *out = (struct stream_out *) context;
1158 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001159 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001161 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1162 set_sched_policy(0, SP_FOREGROUND);
1163 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1164
1165 ALOGV("%s", __func__);
1166 pthread_mutex_lock(&out->lock);
1167 for (;;) {
1168 struct offload_cmd *cmd = NULL;
1169 stream_callback_event_t event;
1170 bool send_callback = false;
1171
1172 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1173 __func__, list_empty(&out->offload_cmd_list),
1174 out->offload_state);
1175 if (list_empty(&out->offload_cmd_list)) {
1176 ALOGV("%s SLEEPING", __func__);
1177 pthread_cond_wait(&out->offload_cond, &out->lock);
1178 ALOGV("%s RUNNING", __func__);
1179 continue;
1180 }
1181
1182 item = list_head(&out->offload_cmd_list);
1183 cmd = node_to_item(item, struct offload_cmd, node);
1184 list_remove(item);
1185
1186 ALOGVV("%s STATE %d CMD %d out->compr %p",
1187 __func__, out->offload_state, cmd->cmd, out->compr);
1188
1189 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1190 free(cmd);
1191 break;
1192 }
1193
1194 if (out->compr == NULL) {
1195 ALOGE("%s: Compress handle is NULL", __func__);
1196 pthread_cond_signal(&out->cond);
1197 continue;
1198 }
1199 out->offload_thread_blocked = true;
1200 pthread_mutex_unlock(&out->lock);
1201 send_callback = false;
1202 switch(cmd->cmd) {
1203 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001204 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001205 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001206 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001207 send_callback = true;
1208 event = STREAM_CBK_EVENT_WRITE_READY;
1209 break;
1210 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001211 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301212 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001213 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301214 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001215 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301216 if (ret < 0)
1217 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301218 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301219 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001220 compress_drain(out->compr);
1221 else
1222 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301223 if (ret != -ENETRESET) {
1224 send_callback = true;
1225 event = STREAM_CBK_EVENT_DRAIN_READY;
1226 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1227 } else
1228 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001229 break;
1230 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001231 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001232 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001233 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001234 send_callback = true;
1235 event = STREAM_CBK_EVENT_DRAIN_READY;
1236 break;
1237 default:
1238 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1239 break;
1240 }
1241 pthread_mutex_lock(&out->lock);
1242 out->offload_thread_blocked = false;
1243 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001244 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001245 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001246 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001247 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001248 free(cmd);
1249 }
1250
1251 pthread_cond_signal(&out->cond);
1252 while (!list_empty(&out->offload_cmd_list)) {
1253 item = list_head(&out->offload_cmd_list);
1254 list_remove(item);
1255 free(node_to_item(item, struct offload_cmd, node));
1256 }
1257 pthread_mutex_unlock(&out->lock);
1258
1259 return NULL;
1260}
1261
1262static int create_offload_callback_thread(struct stream_out *out)
1263{
1264 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1265 list_init(&out->offload_cmd_list);
1266 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1267 offload_thread_loop, out);
1268 return 0;
1269}
1270
1271static int destroy_offload_callback_thread(struct stream_out *out)
1272{
1273 pthread_mutex_lock(&out->lock);
1274 stop_compressed_output_l(out);
1275 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1276
1277 pthread_mutex_unlock(&out->lock);
1278 pthread_join(out->offload_thread, (void **) NULL);
1279 pthread_cond_destroy(&out->offload_cond);
1280
1281 return 0;
1282}
1283
Eric Laurent07eeafd2013-10-06 12:52:49 -07001284static bool allow_hdmi_channel_config(struct audio_device *adev)
1285{
1286 struct listnode *node;
1287 struct audio_usecase *usecase;
1288 bool ret = true;
1289
1290 list_for_each(node, &adev->usecase_list) {
1291 usecase = node_to_item(node, struct audio_usecase, list);
1292 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1293 /*
1294 * If voice call is already existing, do not proceed further to avoid
1295 * disabling/enabling both RX and TX devices, CSD calls, etc.
1296 * Once the voice call done, the HDMI channels can be configured to
1297 * max channels of remaining use cases.
1298 */
1299 if (usecase->id == USECASE_VOICE_CALL) {
1300 ALOGD("%s: voice call is active, no change in HDMI channels",
1301 __func__);
1302 ret = false;
1303 break;
1304 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1305 ALOGD("%s: multi channel playback is active, "
1306 "no change in HDMI channels", __func__);
1307 ret = false;
1308 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001309 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001310 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001311 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1312 ", no change in HDMI channels", __func__,
1313 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001314 ret = false;
1315 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001316 }
1317 }
1318 }
1319 return ret;
1320}
1321
1322static int check_and_set_hdmi_channels(struct audio_device *adev,
1323 unsigned int channels)
1324{
1325 struct listnode *node;
1326 struct audio_usecase *usecase;
1327
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001328 unsigned int supported_channels = platform_edid_get_max_channels(
1329 adev->platform);
1330 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001331 /* Check if change in HDMI channel config is allowed */
1332 if (!allow_hdmi_channel_config(adev))
1333 return 0;
1334
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001335 if (channels > supported_channels)
1336 channels = supported_channels;
1337
Eric Laurent07eeafd2013-10-06 12:52:49 -07001338 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001339 ALOGD("%s: Requested channels are same as current channels(%d)",
1340 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001341 return 0;
1342 }
1343
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001344 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001345 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001346 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001347 adev->cur_hdmi_channels = channels;
1348
1349 /*
1350 * Deroute all the playback streams routed to HDMI so that
1351 * the back end is deactivated. Note that backend will not
1352 * be deactivated if any one stream is connected to it.
1353 */
1354 list_for_each(node, &adev->usecase_list) {
1355 usecase = node_to_item(node, struct audio_usecase, list);
1356 if (usecase->type == PCM_PLAYBACK &&
1357 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001358 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001359 }
1360 }
1361
1362 /*
1363 * Enable all the streams disabled above. Now the HDMI backend
1364 * will be activated with new channel configuration
1365 */
1366 list_for_each(node, &adev->usecase_list) {
1367 usecase = node_to_item(node, struct audio_usecase, list);
1368 if (usecase->type == PCM_PLAYBACK &&
1369 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001370 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001371 }
1372 }
1373
1374 return 0;
1375}
1376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377static int stop_output_stream(struct stream_out *out)
1378{
1379 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001380 struct audio_usecase *uc_info;
1381 struct audio_device *adev = out->dev;
1382
Eric Laurent994a6932013-07-17 11:51:42 -07001383 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001384 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385 uc_info = get_usecase_from_list(adev, out->usecase);
1386 if (uc_info == NULL) {
1387 ALOGE("%s: Could not find the usecase (%d) in the list",
1388 __func__, out->usecase);
1389 return -EINVAL;
1390 }
1391
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001392 if (is_offload_usecase(out->usecase) &&
1393 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001394 if (adev->visualizer_stop_output != NULL)
1395 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001396
1397 audio_extn_dts_remove_state_notifier_node(out->usecase);
1398
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001399 if (adev->offload_effects_stop_output != NULL)
1400 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1401 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001402
Eric Laurent150dbfe2013-02-27 14:31:02 -08001403 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001404 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001405
1406 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001407 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001409 list_remove(&uc_info->list);
1410 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001412 if (is_offload_usecase(out->usecase) &&
1413 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1414 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1415 ALOGV("Disable passthrough , reset mixer to pcm");
1416 /* NO_PASSTHROUGH */
1417 out->compr_config.codec->compr_passthr = 0;
1418 audio_extn_dolby_set_hdmi_config(adev, out);
1419 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1420 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001421 /* Must be called after removing the usecase from list */
1422 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1423 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1424
Eric Laurent994a6932013-07-17 11:51:42 -07001425 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426 return ret;
1427}
1428
1429int start_output_stream(struct stream_out *out)
1430{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001432 int sink_channels = 0;
1433 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 struct audio_usecase *uc_info;
1435 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301436 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001438 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1439 ret = -EINVAL;
1440 goto error_config;
1441 }
1442
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301443 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1444 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1445 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301446
Naresh Tanniru80659832014-06-04 18:17:56 +05301447 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301448 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301449 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301450 goto error_config;
1451 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301452
Eric Laurentb23d5282013-05-14 15:27:20 -07001453 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454 if (out->pcm_device_id < 0) {
1455 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1456 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001457 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001458 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 }
1460
1461 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001462
1463 if (!uc_info) {
1464 ret = -ENOMEM;
1465 goto error_config;
1466 }
1467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468 uc_info->id = out->usecase;
1469 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001470 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471 uc_info->devices = out->devices;
1472 uc_info->in_snd_device = SND_DEVICE_NONE;
1473 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001474 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001475 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001476 if (is_offload_usecase(out->usecase)) {
1477 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001478 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1479 }
1480 }
Mingming Yin9c041392014-05-01 15:37:31 -07001481 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1482 if (!strncmp("true", prop_value, 4)) {
1483 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001484 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1485 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001486 check_and_set_hdmi_channels(adev, sink_channels);
1487 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001488 if (is_offload_usecase(out->usecase)) {
1489 unsigned int ch_count = out->compr_config.codec->ch_in;
1490 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1491 /* backend channel config for passthrough stream is stereo */
1492 ch_count = 2;
1493 check_and_set_hdmi_channels(adev, ch_count);
1494 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001495 check_and_set_hdmi_channels(adev, out->config.channels);
1496 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001497 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001498 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001499 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 select_devices(adev, out->usecase);
1502
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001503 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1504 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001505 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001506 unsigned int flags = PCM_OUT;
1507 unsigned int pcm_open_retry_count = 0;
1508 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1509 flags |= PCM_MMAP | PCM_NOIRQ;
1510 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1511 } else
1512 flags |= PCM_MONOTONIC;
1513
1514 while (1) {
1515 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1516 flags, &out->config);
1517 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1518 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1519 if (out->pcm != NULL) {
1520 pcm_close(out->pcm);
1521 out->pcm = NULL;
1522 }
1523 if (pcm_open_retry_count-- == 0) {
1524 ret = -EIO;
1525 goto error_open;
1526 }
1527 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1528 continue;
1529 }
1530 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001531 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001532 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1533 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001535 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1536 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001538 out->compr = compress_open(adev->snd_card,
1539 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 COMPRESS_IN, &out->compr_config);
1541 if (out->compr && !is_compress_ready(out->compr)) {
1542 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1543 compress_close(out->compr);
1544 out->compr = NULL;
1545 ret = -EIO;
1546 goto error_open;
1547 }
1548 if (out->offload_callback)
1549 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001550
Fred Oh3f43e742015-03-04 18:42:34 -08001551 /* Since small bufs uses blocking writes, a write will be blocked
1552 for the default max poll time (20s) in the event of an SSR.
1553 Reduce the poll time to observe and deal with SSR faster.
1554 */
1555 if (out->use_small_bufs) {
1556 compress_set_max_poll_wait(out->compr, 1000);
1557 }
1558
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001559 audio_extn_dts_create_state_notifier_node(out->usecase);
1560 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1561 popcount(out->channel_mask),
1562 out->playback_started);
1563
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001564#ifdef DS1_DOLBY_DDP_ENABLED
1565 if (audio_extn_is_dolby_format(out->format))
1566 audio_extn_dolby_send_ddp_endp_params(adev);
1567#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001568 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1569 if (adev->visualizer_start_output != NULL)
1570 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1571 if (adev->offload_effects_start_output != NULL)
1572 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001573 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001574 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 }
Eric Laurent994a6932013-07-17 11:51:42 -07001576 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001578error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001580error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001581 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582}
1583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584static int check_input_parameters(uint32_t sample_rate,
1585 audio_format_t format,
1586 int channel_count)
1587{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001588 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001590 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001591 !voice_extn_compress_voip_is_format_supported(format) &&
1592 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001593
1594 switch (channel_count) {
1595 case 1:
1596 case 2:
1597 case 6:
1598 break;
1599 default:
1600 ret = -EINVAL;
1601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001602
1603 switch (sample_rate) {
1604 case 8000:
1605 case 11025:
1606 case 12000:
1607 case 16000:
1608 case 22050:
1609 case 24000:
1610 case 32000:
1611 case 44100:
1612 case 48000:
1613 break;
1614 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001615 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616 }
1617
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001618 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619}
1620
1621static size_t get_input_buffer_size(uint32_t sample_rate,
1622 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001623 int channel_count,
1624 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625{
1626 size_t size = 0;
1627
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001628 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1629 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001631 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001632 if (is_low_latency)
1633 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001634 /* ToDo: should use frame_size computed based on the format and
1635 channel_count here. */
1636 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001638 /* make sure the size is multiple of 32 bytes
1639 * At 48 kHz mono 16-bit PCM:
1640 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1641 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1642 */
1643 size += 0x1f;
1644 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001645
1646 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647}
1648
1649static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1650{
1651 struct stream_out *out = (struct stream_out *)stream;
1652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001653 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654}
1655
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001656static int out_set_sample_rate(struct audio_stream *stream __unused,
1657 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658{
1659 return -ENOSYS;
1660}
1661
1662static size_t out_get_buffer_size(const struct audio_stream *stream)
1663{
1664 struct stream_out *out = (struct stream_out *)stream;
1665
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001666 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001667 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001668 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1669 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001671 return out->config.period_size *
1672 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673}
1674
1675static uint32_t out_get_channels(const struct audio_stream *stream)
1676{
1677 struct stream_out *out = (struct stream_out *)stream;
1678
1679 return out->channel_mask;
1680}
1681
1682static audio_format_t out_get_format(const struct audio_stream *stream)
1683{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684 struct stream_out *out = (struct stream_out *)stream;
1685
1686 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001687}
1688
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001689static int out_set_format(struct audio_stream *stream __unused,
1690 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691{
1692 return -ENOSYS;
1693}
1694
1695static int out_standby(struct audio_stream *stream)
1696{
1697 struct stream_out *out = (struct stream_out *)stream;
1698 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301700 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1701 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001702 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1703 /* Ignore standby in case of voip call because the voip output
1704 * stream is closed in adev_close_output_stream()
1705 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301706 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001707 return 0;
1708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001710 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001712 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001714 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715 if (out->pcm) {
1716 pcm_close(out->pcm);
1717 out->pcm = NULL;
1718 }
1719 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001720 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001722 out->gapless_mdata.encoder_delay = 0;
1723 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724 if (out->compr != NULL) {
1725 compress_close(out->compr);
1726 out->compr = NULL;
1727 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001730 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 }
1732 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001733 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 return 0;
1735}
1736
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001737static int out_dump(const struct audio_stream *stream __unused,
1738 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739{
1740 return 0;
1741}
1742
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001743static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1744{
1745 int ret = 0;
1746 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001747 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001748 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001749 tmp_mdata.encoder_delay = 0;
1750 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001751 tmp_mdata.min_blk_size = 0;
1752 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001753
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001754 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001755 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001756 return -EINVAL;
1757 }
1758
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001759 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1760 if (ret >= 0) {
1761 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1762 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1763 ALOGV("ADTS format is set in offload mode");
1764 }
1765 out->send_new_metadata = 1;
1766 }
1767
Mingming Yin3ee55c62014-08-04 14:23:35 -07001768 if (out->format == AUDIO_FORMAT_FLAC) {
1769 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1770 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001771 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001772 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1773 out->send_new_metadata = 1;
1774 }
1775 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1776 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001777 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001778 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1779 out->send_new_metadata = 1;
1780 }
1781 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1782 if (ret >= 0) {
1783 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1784 out->send_new_metadata = 1;
1785 }
1786 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1787 if (ret >= 0) {
1788 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1789 out->send_new_metadata = 1;
1790 }
1791 }
1792
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001793 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1794 if(ret >= 0)
1795 is_meta_data_params = true;
1796 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1797 if(ret >= 0 )
1798 is_meta_data_params = true;
1799 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1800 if(ret >= 0 )
1801 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001802 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1803 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001804 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001806 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001807 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1808 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001809 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001810 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 }
1812
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001813 if(!is_meta_data_params) {
1814 ALOGV("%s: Not gapless meta data params", __func__);
1815 return 0;
1816 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001817 out->gapless_mdata = tmp_mdata;
1818 out->send_new_metadata = 1;
1819 ALOGV("%s new encoder delay %u and padding %u", __func__,
1820 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1821
1822 return 0;
1823}
1824
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001825static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1826{
1827 return out == adev->primary_output || out == adev->voice_tx_output;
1828}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1831{
1832 struct stream_out *out = (struct stream_out *)stream;
1833 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001834 struct audio_usecase *usecase;
1835 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836 struct str_parms *parms;
1837 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001838 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001839 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840
sangwoobc677242013-08-08 16:53:43 +09001841 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001842 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301844 if (!parms)
1845 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001846 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1847 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001850 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301853 * When HDMI cable is unplugged/usb hs is disconnected the
1854 * music playback is paused and the policy manager sends routing=0
1855 * But the audioflingercontinues to write data until standby time
1856 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001857 * Avoid this by routing audio to speaker until standby.
1858 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301859 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1860 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001862 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1863 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001864 }
1865
1866 /*
1867 * select_devices() call below switches all the usecases on the same
1868 * backend to the new device. Refer to check_usecases_codec_backend() in
1869 * the select_devices(). But how do we undo this?
1870 *
1871 * For example, music playback is active on headset (deep-buffer usecase)
1872 * and if we go to ringtones and select a ringtone, low-latency usecase
1873 * will be started on headset+speaker. As we can't enable headset+speaker
1874 * and headset devices at the same time, select_devices() switches the music
1875 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1876 * So when the ringtone playback is completed, how do we undo the same?
1877 *
1878 * We are relying on the out_set_parameters() call on deep-buffer output,
1879 * once the ringtone playback is ended.
1880 * NOTE: We should not check if the current devices are same as new devices.
1881 * Because select_devices() must be called to switch back the music
1882 * playback to headset.
1883 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001884 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885 out->devices = val;
1886
1887 if (!out->standby)
1888 select_devices(adev, out->usecase);
1889
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001890 if (output_drives_call(adev, out)) {
1891 if(!voice_is_in_call(adev)) {
1892 if (adev->mode == AUDIO_MODE_IN_CALL) {
1893 adev->current_call_output = out;
1894 ret = voice_start_call(adev);
1895 }
1896 } else {
1897 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001898 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001899 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001900 }
1901 }
1902
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001904 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001906
1907 if (out == adev->primary_output) {
1908 pthread_mutex_lock(&adev->lock);
1909 audio_extn_set_parameters(adev, parms);
1910 pthread_mutex_unlock(&adev->lock);
1911 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001912 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001913 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001914 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001915
1916 audio_extn_dts_create_state_notifier_node(out->usecase);
1917 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1918 popcount(out->channel_mask),
1919 out->playback_started);
1920
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001921 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001922 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301925error:
Eric Laurent994a6932013-07-17 11:51:42 -07001926 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 return ret;
1928}
1929
1930static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1931{
1932 struct stream_out *out = (struct stream_out *)stream;
1933 struct str_parms *query = str_parms_create_str(keys);
1934 char *str;
1935 char value[256];
1936 struct str_parms *reply = str_parms_create();
1937 size_t i, j;
1938 int ret;
1939 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001940
1941 if (!query || !reply) {
1942 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1943 return NULL;
1944 }
1945
Eric Laurent994a6932013-07-17 11:51:42 -07001946 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1948 if (ret >= 0) {
1949 value[0] = '\0';
1950 i = 0;
1951 while (out->supported_channel_masks[i] != 0) {
1952 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1953 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1954 if (!first) {
1955 strcat(value, "|");
1956 }
1957 strcat(value, out_channels_name_to_enum_table[j].name);
1958 first = false;
1959 break;
1960 }
1961 }
1962 i++;
1963 }
1964 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1965 str = str_parms_to_str(reply);
1966 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001967 voice_extn_out_get_parameters(out, query, reply);
1968 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001969 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001970 free(str);
1971 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001974
1975 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1976 if (ret >= 0) {
1977 value[0] = '\0';
1978 i = 0;
1979 first = true;
1980 while (out->supported_formats[i] != 0) {
1981 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1982 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1983 if (!first) {
1984 strcat(value, "|");
1985 }
1986 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1987 first = false;
1988 break;
1989 }
1990 }
1991 i++;
1992 }
1993 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
1994 str = str_parms_to_str(reply);
1995 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 str_parms_destroy(query);
1997 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001998 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 return str;
2000}
2001
2002static uint32_t out_get_latency(const struct audio_stream_out *stream)
2003{
2004 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002005 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006
Alexy Josephaa54c872014-12-03 02:46:47 -08002007 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002008 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002009 } else {
2010 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002012 }
2013
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302014 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002015 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016}
2017
2018static int out_set_volume(struct audio_stream_out *stream, float left,
2019 float right)
2020{
Eric Laurenta9024de2013-04-04 09:19:12 -07002021 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 int volume[2];
2023
Eric Laurenta9024de2013-04-04 09:19:12 -07002024 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2025 /* only take left channel into account: the API is for stereo anyway */
2026 out->muted = (left == 0.0f);
2027 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002028 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002029 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2030 /*
2031 * Set mute or umute on HDMI passthrough stream.
2032 * Only take left channel into account.
2033 * Mute is 0 and unmute 1
2034 */
2035 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2036 } else {
2037 char mixer_ctl_name[128];
2038 struct audio_device *adev = out->dev;
2039 struct mixer_ctl *ctl;
2040 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002041 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002043 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2044 "Compress Playback %d Volume", pcm_device_id);
2045 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2046 if (!ctl) {
2047 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2048 __func__, mixer_ctl_name);
2049 return -EINVAL;
2050 }
2051 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2052 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2053 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2054 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002056 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 return -ENOSYS;
2059}
2060
2061static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2062 size_t bytes)
2063{
2064 struct stream_out *out = (struct stream_out *)stream;
2065 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302066 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002067 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302070
Naresh Tanniru80659832014-06-04 18:17:56 +05302071 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002072 // increase written size during SSR to avoid mismatch
2073 // with the written frames count in AF
2074 if (!is_offload_usecase(out->usecase))
2075 out->written += bytes / (out->config.channels * sizeof(short));
2076
Naresh Tanniru80659832014-06-04 18:17:56 +05302077 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302078 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302079 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302080 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002081 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302082 //during SSR for compress usecase we should return error to flinger
2083 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2084 pthread_mutex_unlock(&out->lock);
2085 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302086 }
2087 }
2088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002090 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002091 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002092 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2093 ret = voice_extn_compress_voip_start_output_stream(out);
2094 else
2095 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002096 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002097 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002099 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 goto exit;
2101 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002104 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002105 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002106 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002107 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002108 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2109 out->send_new_metadata = 0;
2110 }
2111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302113 if (ret < 0)
2114 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002115 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002116 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302117 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302119 } else if (-ENETRESET == ret) {
2120 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2121 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2122 pthread_mutex_unlock(&out->lock);
2123 out_standby(&out->stream.common);
2124 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 compress_start(out->compr);
2128 out->playback_started = 1;
2129 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002130
2131 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2132 popcount(out->channel_mask),
2133 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 }
2135 pthread_mutex_unlock(&out->lock);
2136 return ret;
2137 } else {
2138 if (out->pcm) {
2139 if (out->muted)
2140 memset((void *)buffer, 0, bytes);
2141 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002142 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2143 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2144 else
2145 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302146 if (ret < 0)
2147 ret = -errno;
2148 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002149 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002150 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 }
2152
2153exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302154 /* ToDo: There may be a corner case when SSR happens back to back during
2155 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302156 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302157 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302158 }
2159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 pthread_mutex_unlock(&out->lock);
2161
2162 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002163 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002164 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302165 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302166 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302167 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302168 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302169 out->standby = true;
2170 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002172 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302173 out_get_sample_rate(&out->stream.common));
2174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 }
2176 return bytes;
2177}
2178
2179static int out_get_render_position(const struct audio_stream_out *stream,
2180 uint32_t *dsp_frames)
2181{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302183 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002184 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002185 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002186 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 pthread_mutex_lock(&out->lock);
2188 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302189 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302191 if (ret < 0)
2192 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 ALOGVV("%s rendered frames %d sample_rate %d",
2194 __func__, *dsp_frames, out->sample_rate);
2195 }
2196 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302197 if (-ENETRESET == ret) {
2198 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2199 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2200 return -EINVAL;
2201 } else if(ret < 0) {
2202 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2203 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302204 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2205 /*
2206 * Handle corner case where compress session is closed during SSR
2207 * and timestamp is queried
2208 */
2209 ALOGE(" ERROR: sound card not active, return error");
2210 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302211 } else {
2212 return 0;
2213 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 } else
2215 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216}
2217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002218static int out_add_audio_effect(const struct audio_stream *stream __unused,
2219 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220{
2221 return 0;
2222}
2223
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002224static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2225 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226{
2227 return 0;
2228}
2229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002230static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2231 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232{
2233 return -EINVAL;
2234}
2235
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002236static int out_get_presentation_position(const struct audio_stream_out *stream,
2237 uint64_t *frames, struct timespec *timestamp)
2238{
2239 struct stream_out *out = (struct stream_out *)stream;
2240 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002241 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002242
2243 pthread_mutex_lock(&out->lock);
2244
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002245 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002246 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302247 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002248 &out->sample_rate);
2249 ALOGVV("%s rendered frames %ld sample_rate %d",
2250 __func__, dsp_frames, out->sample_rate);
2251 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302252 if (ret < 0)
2253 ret = -errno;
2254 if (-ENETRESET == ret) {
2255 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2256 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2257 ret = -EINVAL;
2258 } else
2259 ret = 0;
2260
Eric Laurent949a0892013-09-20 09:20:13 -07002261 /* this is the best we can do */
2262 clock_gettime(CLOCK_MONOTONIC, timestamp);
2263 }
2264 } else {
2265 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002266 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002267 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2268 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002269 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002270 // This adjustment accounts for buffering after app processor.
2271 // It is based on estimated DSP latency per use case, rather than exact.
2272 signed_frames -=
2273 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2274
Eric Laurent949a0892013-09-20 09:20:13 -07002275 // It would be unusual for this value to be negative, but check just in case ...
2276 if (signed_frames >= 0) {
2277 *frames = signed_frames;
2278 ret = 0;
2279 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002280 }
2281 }
2282 }
2283
2284 pthread_mutex_unlock(&out->lock);
2285
2286 return ret;
2287}
2288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289static int out_set_callback(struct audio_stream_out *stream,
2290 stream_callback_t callback, void *cookie)
2291{
2292 struct stream_out *out = (struct stream_out *)stream;
2293
2294 ALOGV("%s", __func__);
2295 pthread_mutex_lock(&out->lock);
2296 out->offload_callback = callback;
2297 out->offload_cookie = cookie;
2298 pthread_mutex_unlock(&out->lock);
2299 return 0;
2300}
2301
2302static int out_pause(struct audio_stream_out* stream)
2303{
2304 struct stream_out *out = (struct stream_out *)stream;
2305 int status = -ENOSYS;
2306 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002307 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002308 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 pthread_mutex_lock(&out->lock);
2310 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302311 struct audio_device *adev = out->dev;
2312 int snd_scard_state = get_snd_card_state(adev);
2313
2314 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2315 status = compress_pause(out->compr);
2316
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002317 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002318
2319 audio_extn_dts_eagle_fade(adev, false);
2320 audio_extn_dts_notify_playback_state(out->usecase, 0,
2321 out->sample_rate, popcount(out->channel_mask),
2322 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002323 }
2324 pthread_mutex_unlock(&out->lock);
2325 }
2326 return status;
2327}
2328
2329static int out_resume(struct audio_stream_out* stream)
2330{
2331 struct stream_out *out = (struct stream_out *)stream;
2332 int status = -ENOSYS;
2333 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002334 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002335 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 status = 0;
2337 pthread_mutex_lock(&out->lock);
2338 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302339 struct audio_device *adev = out->dev;
2340 int snd_scard_state = get_snd_card_state(adev);
2341
2342 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2343 status = compress_resume(out->compr);
2344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002346
2347 audio_extn_dts_eagle_fade(adev, true);
2348 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2349 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002350 }
2351 pthread_mutex_unlock(&out->lock);
2352 }
2353 return status;
2354}
2355
2356static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2357{
2358 struct stream_out *out = (struct stream_out *)stream;
2359 int status = -ENOSYS;
2360 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002361 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 pthread_mutex_lock(&out->lock);
2363 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2364 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2365 else
2366 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2367 pthread_mutex_unlock(&out->lock);
2368 }
2369 return status;
2370}
2371
2372static int out_flush(struct audio_stream_out* stream)
2373{
2374 struct stream_out *out = (struct stream_out *)stream;
2375 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002376 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002377 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002378 pthread_mutex_lock(&out->lock);
2379 stop_compressed_output_l(out);
2380 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002381 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002382 return 0;
2383 }
2384 return -ENOSYS;
2385}
2386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387/** audio_stream_in implementation **/
2388static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2389{
2390 struct stream_in *in = (struct stream_in *)stream;
2391
2392 return in->config.rate;
2393}
2394
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002395static int in_set_sample_rate(struct audio_stream *stream __unused,
2396 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397{
2398 return -ENOSYS;
2399}
2400
2401static size_t in_get_buffer_size(const struct audio_stream *stream)
2402{
2403 struct stream_in *in = (struct stream_in *)stream;
2404
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002405 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2406 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002407 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2408 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002409
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002410 return in->config.period_size *
2411 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412}
2413
2414static uint32_t in_get_channels(const struct audio_stream *stream)
2415{
2416 struct stream_in *in = (struct stream_in *)stream;
2417
2418 return in->channel_mask;
2419}
2420
2421static audio_format_t in_get_format(const struct audio_stream *stream)
2422{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002423 struct stream_in *in = (struct stream_in *)stream;
2424
2425 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426}
2427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002428static int in_set_format(struct audio_stream *stream __unused,
2429 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430{
2431 return -ENOSYS;
2432}
2433
2434static int in_standby(struct audio_stream *stream)
2435{
2436 struct stream_in *in = (struct stream_in *)stream;
2437 struct audio_device *adev = in->dev;
2438 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302439 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2440 stream, in->usecase, use_case_table[in->usecase]);
2441
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002442 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2443 /* Ignore standby in case of voip call because the voip input
2444 * stream is closed in adev_close_input_stream()
2445 */
2446 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2447 return status;
2448 }
2449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002451 if (!in->standby && in->is_st_session) {
2452 ALOGD("%s: sound trigger pcm stop lab", __func__);
2453 audio_extn_sound_trigger_stop_lab(in);
2454 in->standby = 1;
2455 }
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002458 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002460 if (in->pcm) {
2461 pcm_close(in->pcm);
2462 in->pcm = NULL;
2463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002465 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 }
2467 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002468 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 return status;
2470}
2471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002472static int in_dump(const struct audio_stream *stream __unused,
2473 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474{
2475 return 0;
2476}
2477
2478static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2479{
2480 struct stream_in *in = (struct stream_in *)stream;
2481 struct audio_device *adev = in->dev;
2482 struct str_parms *parms;
2483 char *str;
2484 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002485 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302487 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 parms = str_parms_create_str(kvpairs);
2489
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302490 if (!parms)
2491 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002493 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002494
2495 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2496 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 val = atoi(value);
2498 /* no audio source uses val == 0 */
2499 if ((in->source != val) && (val != 0)) {
2500 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002501 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2502 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2503 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2504 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002505 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002506 err = voice_extn_compress_voip_open_input_stream(in);
2507 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002508 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002509 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002510 }
2511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 }
2513 }
2514
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002515 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2516 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002518 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 in->device = val;
2520 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002521 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002522 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 }
2524 }
2525
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002526done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002528 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529
2530 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302531error:
Eric Laurent994a6932013-07-17 11:51:42 -07002532 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 return ret;
2534}
2535
2536static char* in_get_parameters(const struct audio_stream *stream,
2537 const char *keys)
2538{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002539 struct stream_in *in = (struct stream_in *)stream;
2540 struct str_parms *query = str_parms_create_str(keys);
2541 char *str;
2542 char value[256];
2543 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002544
2545 if (!query || !reply) {
2546 ALOGE("in_get_parameters: failed to create query or reply");
2547 return NULL;
2548 }
2549
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002550 ALOGV("%s: enter: keys - %s", __func__, keys);
2551
2552 voice_extn_in_get_parameters(in, query, reply);
2553
2554 str = str_parms_to_str(reply);
2555 str_parms_destroy(query);
2556 str_parms_destroy(reply);
2557
2558 ALOGV("%s: exit: returns - %s", __func__, str);
2559 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560}
2561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002562static int in_set_gain(struct audio_stream_in *stream __unused,
2563 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564{
2565 return 0;
2566}
2567
2568static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2569 size_t bytes)
2570{
2571 struct stream_in *in = (struct stream_in *)stream;
2572 struct audio_device *adev = in->dev;
2573 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302574 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302577
2578 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302579 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302580 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302581 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302582 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002583 } else {
2584 if (in->is_st_session && !in->is_st_session_active) {
2585 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2586 ret= -EIO;;
2587 goto exit;
2588 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302589 }
2590 }
2591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002593 if (!in->is_st_session) {
2594 pthread_mutex_lock(&adev->lock);
2595 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2596 ret = voice_extn_compress_voip_start_input_stream(in);
2597 else
2598 ret = start_input_stream(in);
2599 pthread_mutex_unlock(&adev->lock);
2600 if (ret != 0) {
2601 goto exit;
2602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 }
2604 in->standby = 0;
2605 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606
2607 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002608 if (audio_extn_ssr_get_enabled() &&
2609 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002610 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002611 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2612 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002613 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2614 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002615 else
2616 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302617 if (ret < 0)
2618 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 }
2620
2621 /*
2622 * Instead of writing zeroes here, we could trust the hardware
2623 * to always provide zeroes when muted.
2624 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302625 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2626 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 memset(buffer, 0, bytes);
2628
2629exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302630 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302631 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302632 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002633 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2634 session reading on LAB data. In this case do not set sound card state
2635 offline, instead mark this sound trigger session inactive to avoid
2636 further reading of LAB data from CPE driver. Marking the session
2637 inactive handles both CPE and ADSP SSR for sound trigger session */
2638 if (!in->is_st_session)
2639 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2640 else
2641 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302642 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 pthread_mutex_unlock(&in->lock);
2644
2645 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302646 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302647 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302648 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302649 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302650 in->standby = true;
2651 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302652 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002654 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002655 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302656 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 }
2658 return bytes;
2659}
2660
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002661static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662{
2663 return 0;
2664}
2665
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002666static int add_remove_audio_effect(const struct audio_stream *stream,
2667 effect_handle_t effect,
2668 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002670 struct stream_in *in = (struct stream_in *)stream;
2671 int status = 0;
2672 effect_descriptor_t desc;
2673
2674 status = (*effect)->get_descriptor(effect, &desc);
2675 if (status != 0)
2676 return status;
2677
2678 pthread_mutex_lock(&in->lock);
2679 pthread_mutex_lock(&in->dev->lock);
2680 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2681 in->enable_aec != enable &&
2682 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2683 in->enable_aec = enable;
2684 if (!in->standby)
2685 select_devices(in->dev, in->usecase);
2686 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002687 if (in->enable_ns != enable &&
2688 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2689 in->enable_ns = enable;
2690 if (!in->standby)
2691 select_devices(in->dev, in->usecase);
2692 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002693 pthread_mutex_unlock(&in->dev->lock);
2694 pthread_mutex_unlock(&in->lock);
2695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 return 0;
2697}
2698
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002699static int in_add_audio_effect(const struct audio_stream *stream,
2700 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701{
Eric Laurent994a6932013-07-17 11:51:42 -07002702 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002703 return add_remove_audio_effect(stream, effect, true);
2704}
2705
2706static int in_remove_audio_effect(const struct audio_stream *stream,
2707 effect_handle_t effect)
2708{
Eric Laurent994a6932013-07-17 11:51:42 -07002709 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711}
2712
2713static int adev_open_output_stream(struct audio_hw_device *dev,
2714 audio_io_handle_t handle,
2715 audio_devices_t devices,
2716 audio_output_flags_t flags,
2717 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002718 struct audio_stream_out **stream_out,
2719 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720{
2721 struct audio_device *adev = (struct audio_device *)dev;
2722 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002723 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002724 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302727
2728 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2729 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2730 ALOGE(" sound card is not active rejecting compress output open request");
2731 return -EINVAL;
2732 }
2733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2735
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302736 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2737 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2738 devices, flags, &out->stream);
2739
2740
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002741 if (!out) {
2742 return -ENOMEM;
2743 }
2744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745 if (devices == AUDIO_DEVICE_NONE)
2746 devices = AUDIO_DEVICE_OUT_SPEAKER;
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 out->flags = flags;
2749 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002750 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002751 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 out->sample_rate = config->sample_rate;
2753 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2754 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002755 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002756 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002757 out->non_blocking = 0;
2758 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759
2760 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002761 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2762 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2763 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2764
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002765 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002766 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2767 ret = read_hdmi_channel_masks(out);
2768
2769 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2770 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002771 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002772 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002773 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002774
2775 if (config->sample_rate == 0)
2776 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2777 if (config->channel_mask == 0)
2778 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2779
2780 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002781 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2783 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002785 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002787 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2788 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002789 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002790 ret = voice_extn_compress_voip_open_output_stream(out);
2791 if (ret != 0) {
2792 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2793 __func__, ret);
2794 goto error_open;
2795 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002796 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2797 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2798 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2799 ALOGE("%s: Unsupported Offload information", __func__);
2800 ret = -EINVAL;
2801 goto error_open;
2802 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002803
2804 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2805 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2806 ALOGV("read and update_pass through formats");
2807 ret = audio_extn_dolby_update_passt_formats(adev, out);
2808 if(ret != 0) {
2809 goto error_open;
2810 }
2811 if(config->offload_info.format == 0)
2812 config->offload_info.format = out->supported_formats[0];
2813 }
2814
Mingming Yin90310102013-11-13 16:57:00 -08002815 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002816 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 ALOGE("%s: Unsupported audio format", __func__);
2818 ret = -EINVAL;
2819 goto error_open;
2820 }
2821
2822 out->compr_config.codec = (struct snd_codec *)
2823 calloc(1, sizeof(struct snd_codec));
2824
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002825 if (!out->compr_config.codec) {
2826 ret = -ENOMEM;
2827 goto error_open;
2828 }
2829
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002830 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002831 if (config->offload_info.channel_mask)
2832 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002833 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002834 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002835 config->offload_info.channel_mask = config->channel_mask;
2836 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002837 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 out->sample_rate = config->offload_info.sample_rate;
2839
2840 out->stream.set_callback = out_set_callback;
2841 out->stream.pause = out_pause;
2842 out->stream.resume = out_resume;
2843 out->stream.drain = out_drain;
2844 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002845 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002847 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002848 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002849 audio_extn_dolby_get_snd_codec_id(adev, out,
2850 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002851 else
2852 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002854 if (audio_is_offload_pcm(config->offload_info.format)) {
2855 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002856 platform_get_pcm_offload_buffer_size(&config->offload_info);
2857 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2858 out->compr_config.fragment_size =
2859 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002860 } else {
2861 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002862 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002863 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2865 out->compr_config.codec->sample_rate =
2866 compress_get_alsa_rate(config->offload_info.sample_rate);
2867 out->compr_config.codec->bit_rate =
2868 config->offload_info.bit_rate;
2869 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002870 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002872 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002873 /*TODO: Do we need to change it for passthrough */
2874 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875
Mingming Yin3ee55c62014-08-04 14:23:35 -07002876 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2877 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002878 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2879 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002880 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002881 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2882
Mingming Yin3ee55c62014-08-04 14:23:35 -07002883 if (out->bit_width == 24) {
2884 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2885 }
2886
Amit Shekhar6f461b12014-08-01 14:52:58 -07002887 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002888 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002889
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2891 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002892
Alexy Josephaa54c872014-12-03 02:46:47 -08002893 if (config->offload_info.use_small_bufs) {
2894 //this flag is set from framework only if its for PCM formats
2895 //no need to check for PCM format again
2896 out->non_blocking = 0;
2897 out->use_small_bufs = true;
2898 ALOGI("Keep write blocking for small buff: non_blockling %d",
2899 out->non_blocking);
2900 }
2901
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002902 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002903 out->offload_state = OFFLOAD_STATE_IDLE;
2904 out->playback_started = 0;
2905
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002906 audio_extn_dts_create_state_notifier_node(out->usecase);
2907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 create_offload_callback_thread(out);
2909 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2910 __func__, config->offload_info.version,
2911 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002912 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002913 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002914 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2915 ret = voice_check_and_set_incall_music_usecase(adev, out);
2916 if (ret != 0) {
2917 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2918 __func__, ret);
2919 goto error_open;
2920 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002921 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2922 if (config->sample_rate == 0)
2923 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2924 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2925 config->sample_rate != 8000) {
2926 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2927 ret = -EINVAL;
2928 goto error_open;
2929 }
2930 out->sample_rate = config->sample_rate;
2931 out->config.rate = config->sample_rate;
2932 if (config->format == AUDIO_FORMAT_DEFAULT)
2933 config->format = AUDIO_FORMAT_PCM_16_BIT;
2934 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2935 config->format = AUDIO_FORMAT_PCM_16_BIT;
2936 ret = -EINVAL;
2937 goto error_open;
2938 }
2939 out->format = config->format;
2940 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2941 out->config = pcm_config_afe_proxy_playback;
2942 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002943 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002944 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2946 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002948 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002949 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002950 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002951 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002952 out->config = pcm_config_deep_buffer;
2953 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 }
2955
Amit Shekhar1d896042014-10-03 13:16:09 -07002956 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2957 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002958 /* TODO remove this hardcoding and check why width is zero*/
2959 if (out->bit_width == 0)
2960 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002961 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2962 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002963 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002964 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002965 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2966 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2967 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002968 if(adev->primary_output == NULL)
2969 adev->primary_output = out;
2970 else {
2971 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002972 ret = -EEXIST;
2973 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002974 }
2975 }
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 /* Check if this usecase is already existing */
2978 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002979 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2980 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002983 ret = -EEXIST;
2984 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 }
2986 pthread_mutex_unlock(&adev->lock);
2987
2988 out->stream.common.get_sample_rate = out_get_sample_rate;
2989 out->stream.common.set_sample_rate = out_set_sample_rate;
2990 out->stream.common.get_buffer_size = out_get_buffer_size;
2991 out->stream.common.get_channels = out_get_channels;
2992 out->stream.common.get_format = out_get_format;
2993 out->stream.common.set_format = out_set_format;
2994 out->stream.common.standby = out_standby;
2995 out->stream.common.dump = out_dump;
2996 out->stream.common.set_parameters = out_set_parameters;
2997 out->stream.common.get_parameters = out_get_parameters;
2998 out->stream.common.add_audio_effect = out_add_audio_effect;
2999 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3000 out->stream.get_latency = out_get_latency;
3001 out->stream.set_volume = out_set_volume;
3002 out->stream.write = out_write;
3003 out->stream.get_render_position = out_get_render_position;
3004 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003005 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003008 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003009 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003011 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3012 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 config->format = out->stream.common.get_format(&out->stream.common);
3015 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3016 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3017
3018 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303019 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3020 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003021
3022 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3023 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3024 popcount(out->channel_mask), out->playback_started);
3025
Eric Laurent994a6932013-07-17 11:51:42 -07003026 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003028
3029error_open:
3030 free(out);
3031 *stream_out = NULL;
3032 ALOGD("%s: exit: ret %d", __func__, ret);
3033 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034}
3035
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003036static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 struct audio_stream_out *stream)
3038{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039 struct stream_out *out = (struct stream_out *)stream;
3040 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003041 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303043 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3044
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003045 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303046 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003047 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303048 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003049 if(ret != 0)
3050 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3051 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003052 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003053 out_standby(&stream->common);
3054
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003055 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003056 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003058 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 if (out->compr_config.codec != NULL)
3060 free(out->compr_config.codec);
3061 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003062
3063 if (adev->voice_tx_output == out)
3064 adev->voice_tx_output = NULL;
3065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 pthread_cond_destroy(&out->cond);
3067 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003069 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070}
3071
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003072static void close_compress_sessions(struct audio_device *adev)
3073{
Mingming Yin7b762e72015-03-04 13:47:32 -08003074 struct stream_out *out;
3075 struct listnode *node;
3076 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003077 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003078 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003079 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003080 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003081 if (usecase && usecase->stream.out) {
3082 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3083 out = usecase->stream.out;
3084 pthread_mutex_unlock(&adev->lock);
3085 out_standby(&out->stream.common);
3086 pthread_mutex_lock(&adev->lock);
3087 }
3088 }
3089 }
3090 pthread_mutex_unlock(&adev->lock);
3091}
3092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3094{
3095 struct audio_device *adev = (struct audio_device *)dev;
3096 struct str_parms *parms;
3097 char *str;
3098 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003099 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003100 int ret;
3101 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003103 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303106 if (!parms)
3107 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003108 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3109 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303110 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303111 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303112 struct listnode *node;
3113 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303114 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303115 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003116 //close compress sessions on OFFLINE status
3117 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303118 } else if (strstr(snd_card_status, "ONLINE")) {
3119 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303120 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303121 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303122 }
3123
3124 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003125 status = voice_set_parameters(adev, parms);
3126 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003127 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003129 status = platform_set_parameters(adev->platform, parms);
3130 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003131 goto done;
3132
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003133 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3134 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003135 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3137 adev->bluetooth_nrec = true;
3138 else
3139 adev->bluetooth_nrec = false;
3140 }
3141
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003142 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3143 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3145 adev->screen_off = false;
3146 else
3147 adev->screen_off = true;
3148 }
3149
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003150 ret = str_parms_get_int(parms, "rotation", &val);
3151 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003152 bool reverse_speakers = false;
3153 switch(val) {
3154 // FIXME: note that the code below assumes that the speakers are in the correct placement
3155 // relative to the user when the device is rotated 90deg from its default rotation. This
3156 // assumption is device-specific, not platform-specific like this code.
3157 case 270:
3158 reverse_speakers = true;
3159 break;
3160 case 0:
3161 case 90:
3162 case 180:
3163 break;
3164 default:
3165 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003166 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003167 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003168 if (status == 0) {
3169 if (adev->speaker_lr_swap != reverse_speakers) {
3170 adev->speaker_lr_swap = reverse_speakers;
3171 // only update the selected device if there is active pcm playback
3172 struct audio_usecase *usecase;
3173 struct listnode *node;
3174 list_for_each(node, &adev->usecase_list) {
3175 usecase = node_to_item(node, struct audio_usecase, list);
3176 if (usecase->type == PCM_PLAYBACK) {
3177 select_devices(adev, usecase->id);
3178 break;
3179 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003180 }
3181 }
3182 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003183 }
3184
Mingming Yin514a8bc2014-07-29 15:22:21 -07003185 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3186 if (ret >= 0) {
3187 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3188 adev->bt_wb_speech_enabled = true;
3189 else
3190 adev->bt_wb_speech_enabled = false;
3191 }
3192
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003193 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3194 if (ret >= 0) {
3195 val = atoi(value);
3196 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3197 ALOGV("cache new edid");
3198 platform_cache_edid(adev->platform);
3199 }
3200 }
3201
3202 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3203 if (ret >= 0) {
3204 val = atoi(value);
3205 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3206 ALOGV("invalidate cached edid");
3207 platform_invalidate_edid(adev->platform);
3208 }
3209 }
3210
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003211 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003212
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003213done:
3214 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003215 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303216error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003217 ALOGV("%s: exit with code(%d)", __func__, status);
3218 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219}
3220
3221static char* adev_get_parameters(const struct audio_hw_device *dev,
3222 const char *keys)
3223{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003224 struct audio_device *adev = (struct audio_device *)dev;
3225 struct str_parms *reply = str_parms_create();
3226 struct str_parms *query = str_parms_create_str(keys);
3227 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303228 char value[256] = {0};
3229 int ret = 0;
3230
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003231 if (!query || !reply) {
3232 ALOGE("adev_get_parameters: failed to create query or reply");
3233 return NULL;
3234 }
3235
Naresh Tannirud7205b62014-06-20 02:54:48 +05303236 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3237 sizeof(value));
3238 if (ret >=0) {
3239 int val = 1;
3240 pthread_mutex_lock(&adev->snd_card_status.lock);
3241 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3242 val = 0;
3243 pthread_mutex_unlock(&adev->snd_card_status.lock);
3244 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3245 goto exit;
3246 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003247
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003248 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003249 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003250 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003251 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303252 pthread_mutex_unlock(&adev->lock);
3253
Naresh Tannirud7205b62014-06-20 02:54:48 +05303254exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003255 str = str_parms_to_str(reply);
3256 str_parms_destroy(query);
3257 str_parms_destroy(reply);
3258
3259 ALOGV("%s: exit: returns - %s", __func__, str);
3260 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261}
3262
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003263static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264{
3265 return 0;
3266}
3267
3268static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3269{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003270 int ret;
3271 struct audio_device *adev = (struct audio_device *)dev;
3272 pthread_mutex_lock(&adev->lock);
3273 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003274 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003275 pthread_mutex_unlock(&adev->lock);
3276 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277}
3278
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003279static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3280 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281{
3282 return -ENOSYS;
3283}
3284
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003285static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3286 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287{
3288 return -ENOSYS;
3289}
3290
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003291static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3292 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293{
3294 return -ENOSYS;
3295}
3296
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003297static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3298 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299{
3300 return -ENOSYS;
3301}
3302
3303static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3304{
3305 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 pthread_mutex_lock(&adev->lock);
3308 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003309 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003311 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3312 voice_is_in_call(adev)) {
3313 voice_stop_call(adev);
3314 adev->current_call_output = NULL;
3315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 }
3317 pthread_mutex_unlock(&adev->lock);
3318 return 0;
3319}
3320
3321static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3322{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003323 int ret;
3324
3325 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003326 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003327 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3328 pthread_mutex_unlock(&adev->lock);
3329
3330 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
3333static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3334{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003335 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 return 0;
3337}
3338
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003339static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 const struct audio_config *config)
3341{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003342 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003344 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3345 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346}
3347
3348static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003349 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 audio_devices_t devices,
3351 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003352 struct audio_stream_in **stream_in,
3353 audio_input_flags_t flags __unused,
3354 const char *address __unused,
3355 audio_source_t source __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356{
3357 struct audio_device *adev = (struct audio_device *)dev;
3358 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003359 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003360 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003361 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 *stream_in = NULL;
3364 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3365 return -EINVAL;
3366
3367 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003368
3369 if (!in) {
3370 ALOGE("failed to allocate input stream");
3371 return -ENOMEM;
3372 }
3373
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303374 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003375 stream_handle(%p) io_handle(%d)",__func__, config->sample_rate, config->channel_mask,
3376 devices, &in->stream, handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003378 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 in->stream.common.get_sample_rate = in_get_sample_rate;
3381 in->stream.common.set_sample_rate = in_set_sample_rate;
3382 in->stream.common.get_buffer_size = in_get_buffer_size;
3383 in->stream.common.get_channels = in_get_channels;
3384 in->stream.common.get_format = in_get_format;
3385 in->stream.common.set_format = in_set_format;
3386 in->stream.common.standby = in_standby;
3387 in->stream.common.dump = in_dump;
3388 in->stream.common.set_parameters = in_set_parameters;
3389 in->stream.common.get_parameters = in_get_parameters;
3390 in->stream.common.add_audio_effect = in_add_audio_effect;
3391 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3392 in->stream.set_gain = in_set_gain;
3393 in->stream.read = in_read;
3394 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3395
3396 in->device = devices;
3397 in->source = AUDIO_SOURCE_DEFAULT;
3398 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 in->standby = 1;
3400 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003401 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
3403 /* Update config params with the requested sample rate and channels */
3404 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003405 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3406 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3407 is_low_latency = true;
3408#if LOW_LATENCY_CAPTURE_USE_CASE
3409 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3410#endif
3411 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003414 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003416 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303417 if (adev->mode != AUDIO_MODE_IN_CALL) {
3418 ret = -EINVAL;
3419 goto err_open;
3420 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003421 if (config->sample_rate == 0)
3422 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3423 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3424 config->sample_rate != 8000) {
3425 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3426 ret = -EINVAL;
3427 goto err_open;
3428 }
3429 if (config->format == AUDIO_FORMAT_DEFAULT)
3430 config->format = AUDIO_FORMAT_PCM_16_BIT;
3431 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3432 config->format = AUDIO_FORMAT_PCM_16_BIT;
3433 ret = -EINVAL;
3434 goto err_open;
3435 }
3436
3437 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3438 in->config = pcm_config_afe_proxy_record;
3439 in->config.channels = channel_count;
3440 in->config.rate = config->sample_rate;
3441 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003442 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003443 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003444 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3445 ret = -EINVAL;
3446 goto err_open;
3447 }
3448 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003449 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003450 }
Mingming Yine62d7842013-10-25 16:26:03 -07003451 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003452 audio_extn_compr_cap_format_supported(config->format) &&
3453 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003454 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003455 } else {
3456 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003457 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003458 buffer_size = get_input_buffer_size(config->sample_rate,
3459 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003460 channel_count,
3461 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003462 in->config.period_size = buffer_size / frame_size;
3463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003465 /* This stream could be for sound trigger lab,
3466 get sound trigger pcm if present */
3467 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303468 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003471 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003472 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473
3474err_open:
3475 free(in);
3476 *stream_in = NULL;
3477 return ret;
3478}
3479
3480static void adev_close_input_stream(struct audio_hw_device *dev,
3481 struct audio_stream_in *stream)
3482{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003483 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003484 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003485 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303486
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303487 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003488
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303489 /* Disable echo reference while closing input stream */
3490 platform_set_echo_reference(adev->platform, false);
3491
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003492 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303493 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003494 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303495 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003496 if (ret != 0)
3497 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3498 __func__, ret);
3499 } else
3500 in_standby(&stream->common);
3501
Mingming Yin7b762e72015-03-04 13:47:32 -08003502 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003503 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003504 audio_extn_ssr_deinit();
3505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506
Mingming Yine62d7842013-10-25 16:26:03 -07003507 if(audio_extn_compr_cap_enabled() &&
3508 audio_extn_compr_cap_format_supported(in->config.format))
3509 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003510
3511 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 return;
3513}
3514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003515static int adev_dump(const audio_hw_device_t *device __unused,
3516 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517{
3518 return 0;
3519}
3520
3521static int adev_close(hw_device_t *device)
3522{
3523 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003524
3525 if (!adev)
3526 return 0;
3527
3528 pthread_mutex_lock(&adev_init_lock);
3529
3530 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003531 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003532 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003533 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003534 audio_route_free(adev->audio_route);
3535 free(adev->snd_dev_ref_cnt);
3536 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003537 free(device);
3538 adev = NULL;
3539 }
3540 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003541 return 0;
3542}
3543
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003544/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3545 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3546 * just that it _might_ work.
3547 */
3548static int period_size_is_plausible_for_low_latency(int period_size)
3549{
3550 switch (period_size) {
3551 case 160:
3552 case 240:
3553 case 320:
3554 case 480:
3555 return 1;
3556 default:
3557 return 0;
3558 }
3559}
3560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561static int adev_open(const hw_module_t *module, const char *name,
3562 hw_device_t **device)
3563{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003564 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003566 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3568
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003569 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003570 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003571 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003572 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003573 ALOGD("%s: returning existing instance of adev", __func__);
3574 ALOGD("%s: exit", __func__);
3575 pthread_mutex_unlock(&adev_init_lock);
3576 return 0;
3577 }
3578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 adev = calloc(1, sizeof(struct audio_device));
3580
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003581 if (!adev) {
3582 pthread_mutex_unlock(&adev_init_lock);
3583 return -ENOMEM;
3584 }
3585
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003586 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3589 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3590 adev->device.common.module = (struct hw_module_t *)module;
3591 adev->device.common.close = adev_close;
3592
3593 adev->device.init_check = adev_init_check;
3594 adev->device.set_voice_volume = adev_set_voice_volume;
3595 adev->device.set_master_volume = adev_set_master_volume;
3596 adev->device.get_master_volume = adev_get_master_volume;
3597 adev->device.set_master_mute = adev_set_master_mute;
3598 adev->device.get_master_mute = adev_get_master_mute;
3599 adev->device.set_mode = adev_set_mode;
3600 adev->device.set_mic_mute = adev_set_mic_mute;
3601 adev->device.get_mic_mute = adev_get_mic_mute;
3602 adev->device.set_parameters = adev_set_parameters;
3603 adev->device.get_parameters = adev_get_parameters;
3604 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3605 adev->device.open_output_stream = adev_open_output_stream;
3606 adev->device.close_output_stream = adev_close_output_stream;
3607 adev->device.open_input_stream = adev_open_input_stream;
3608 adev->device.close_input_stream = adev_close_input_stream;
3609 adev->device.dump = adev_dump;
3610
3611 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003613 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003614 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003617 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003618 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003619 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3620 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003621 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003622 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003623 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003624 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003625 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303626
3627 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3628 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003630 adev->platform = platform_init(adev);
3631 if (!adev->platform) {
3632 free(adev->snd_dev_ref_cnt);
3633 free(adev);
3634 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3635 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003636 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003637 return -EINVAL;
3638 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003639
Naresh Tanniru4c630392014-05-12 01:05:52 +05303640 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3641
Eric Laurentc4aef752013-09-12 17:45:53 -07003642 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3643 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3644 if (adev->visualizer_lib == NULL) {
3645 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3646 } else {
3647 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3648 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003649 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003650 "visualizer_hal_start_output");
3651 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003652 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003653 "visualizer_hal_stop_output");
3654 }
3655 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003656 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003657 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003658
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003659 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3660 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3661 if (adev->offload_effects_lib == NULL) {
3662 ALOGE("%s: DLOPEN failed for %s", __func__,
3663 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3664 } else {
3665 ALOGV("%s: DLOPEN successful for %s", __func__,
3666 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3667 adev->offload_effects_start_output =
3668 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3669 "offload_effects_bundle_hal_start_output");
3670 adev->offload_effects_stop_output =
3671 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3672 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003673 adev->offload_effects_set_hpx_state =
3674 (int (*)(bool))dlsym(adev->offload_effects_lib,
3675 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003676 }
3677 }
3678
Mingming Yin514a8bc2014-07-29 15:22:21 -07003679 adev->bt_wb_speech_enabled = false;
3680
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003681 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 *device = &adev->device.common;
3683
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003684 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3685 &adev->streams_output_cfg_list);
3686
Kiran Kandi910e1862013-10-29 13:29:42 -07003687 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003688
3689 char value[PROPERTY_VALUE_MAX];
3690 int trial;
3691 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3692 trial = atoi(value);
3693 if (period_size_is_plausible_for_low_latency(trial)) {
3694 pcm_config_low_latency.period_size = trial;
3695 pcm_config_low_latency.start_threshold = trial / 4;
3696 pcm_config_low_latency.avail_min = trial / 4;
3697 configured_low_latency_capture_period_size = trial;
3698 }
3699 }
3700 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3701 trial = atoi(value);
3702 if (period_size_is_plausible_for_low_latency(trial)) {
3703 configured_low_latency_capture_period_size = trial;
3704 }
3705 }
3706
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003707 pthread_mutex_unlock(&adev_init_lock);
3708
Eric Laurent994a6932013-07-17 11:51:42 -07003709 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 return 0;
3711}
3712
3713static struct hw_module_methods_t hal_module_methods = {
3714 .open = adev_open,
3715};
3716
3717struct audio_module HAL_MODULE_INFO_SYM = {
3718 .common = {
3719 .tag = HARDWARE_MODULE_TAG,
3720 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3721 .hal_api_version = HARDWARE_HAL_API_VERSION,
3722 .id = AUDIO_HARDWARE_MODULE_ID,
3723 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003724 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 .methods = &hal_module_methods,
3726 },
3727};