blob: 24852b642a29852183e7416c2c051192d727b0c6 [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 */
78#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
79#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 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800468 if (audio_extn_spkr_prot_start_processing(snd_device)) {
469 ALOGE("%s: spkr_start_processing failed", __func__);
470 return -EINVAL;
471 }
472 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700473 ALOGV("%s: snd_device(%d: %s)", __func__,
474 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700475 /* due to the possibility of calibration overwrite between listen
476 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700477 audio_extn_sound_trigger_update_device_status(snd_device,
478 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530479 audio_extn_listen_update_device_status(snd_device,
480 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700481 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700482 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700483 audio_extn_sound_trigger_update_device_status(snd_device,
484 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530485 audio_extn_listen_update_device_status(snd_device,
486 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700487 return -EINVAL;
488 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300489 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700490 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800492 return 0;
493}
494
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700495int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700496 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800497{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700498 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
499
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800500 if (snd_device < SND_DEVICE_MIN ||
501 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800502 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800503 return -EINVAL;
504 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
506 ALOGE("%s: device ref cnt is already 0", __func__);
507 return -EINVAL;
508 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700509
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700510 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700511
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700512 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
513 ALOGE("%s: Invalid sound device returned", __func__);
514 return -EINVAL;
515 }
516
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700517 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700518 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700519 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800520 /* exit usb play back thread */
521 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
522 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
523 audio_extn_usb_stop_playback();
524
525 /* exit usb capture thread */
526 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700527 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800528
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800529 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
530 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700531 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700532 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300533 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700534 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300535 audio_extn_dev_arbi_release(snd_device);
536 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700537
538 audio_extn_sound_trigger_update_device_status(snd_device,
539 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530540 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800541 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 return 0;
545}
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547static void check_usecases_codec_backend(struct audio_device *adev,
548 struct audio_usecase *uc_info,
549 snd_device_t snd_device)
550{
551 struct listnode *node;
552 struct audio_usecase *usecase;
553 bool switch_device[AUDIO_USECASE_MAX];
554 int i, num_uc_to_switch = 0;
555
556 /*
557 * This function is to make sure that all the usecases that are active on
558 * the hardware codec backend are always routed to any one device that is
559 * handled by the hardware codec.
560 * For example, if low-latency and deep-buffer usecases are currently active
561 * on speaker and out_set_parameters(headset) is received on low-latency
562 * output, then we have to make sure deep-buffer is also switched to headset,
563 * because of the limitation that both the devices cannot be enabled
564 * at the same time as they share the same backend.
565 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700566 /*
567 * This call is to check if we need to force routing for a particular stream
568 * If there is a backend configuration change for the device when a
569 * new stream starts, then ADM needs to be closed and re-opened with the new
570 * configuraion. This call check if we need to re-route all the streams
571 * associated with the backend. Touch tone + 24 bit playback.
572 */
573 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
574
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 /* Disable all the usecases on the shared backend other than the
576 specified usecase */
577 for (i = 0; i < AUDIO_USECASE_MAX; i++)
578 switch_device[i] = false;
579
580 list_for_each(node, &adev->usecase_list) {
581 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800582 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700584 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
586 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
587 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700588 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700589 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590 switch_device[usecase->id] = true;
591 num_uc_to_switch++;
592 }
593 }
594
595 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700596 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700597
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530598 /* Make sure the previous devices to be disabled first and then enable the
599 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 list_for_each(node, &adev->usecase_list) {
601 usecase = node_to_item(node, struct audio_usecase, list);
602 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700603 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700604 }
605 }
606
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700607 list_for_each(node, &adev->usecase_list) {
608 usecase = node_to_item(node, struct audio_usecase, list);
609 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700610 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700611 }
612 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 /* Re-route all the usecases on the shared backend other than the
615 specified usecase to new snd devices */
616 list_for_each(node, &adev->usecase_list) {
617 usecase = node_to_item(node, struct audio_usecase, list);
618 /* Update the out_snd_device only before enabling the audio route */
619 if (switch_device[usecase->id] ) {
620 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800621 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530622 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623 }
624 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625 }
626}
627
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700628static void check_and_route_capture_usecases(struct audio_device *adev,
629 struct audio_usecase *uc_info,
630 snd_device_t snd_device)
631{
632 struct listnode *node;
633 struct audio_usecase *usecase;
634 bool switch_device[AUDIO_USECASE_MAX];
635 int i, num_uc_to_switch = 0;
636
637 /*
638 * This function is to make sure that all the active capture usecases
639 * are always routed to the same input sound device.
640 * For example, if audio-record and voice-call usecases are currently
641 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
642 * is received for voice call then we have to make sure that audio-record
643 * usecase is also switched to earpiece i.e. voice-dmic-ef,
644 * because of the limitation that two devices cannot be enabled
645 * at the same time if they share the same backend.
646 */
647 for (i = 0; i < AUDIO_USECASE_MAX; i++)
648 switch_device[i] = false;
649
650 list_for_each(node, &adev->usecase_list) {
651 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800652 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700653 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700654 usecase->in_snd_device != snd_device &&
655 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700656 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
657 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700658 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700659 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700660 switch_device[usecase->id] = true;
661 num_uc_to_switch++;
662 }
663 }
664
665 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700666 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700667
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530668 /* Make sure the previous devices to be disabled first and then enable the
669 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670 list_for_each(node, &adev->usecase_list) {
671 usecase = node_to_item(node, struct audio_usecase, list);
672 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700673 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800674 }
675 }
676
677 list_for_each(node, &adev->usecase_list) {
678 usecase = node_to_item(node, struct audio_usecase, list);
679 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700680 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700681 }
682 }
683
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700684 /* Re-route all the usecases on the shared backend other than the
685 specified usecase to new snd devices */
686 list_for_each(node, &adev->usecase_list) {
687 usecase = node_to_item(node, struct audio_usecase, list);
688 /* Update the in_snd_device only before enabling the audio route */
689 if (switch_device[usecase->id] ) {
690 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800691 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530692 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693 }
694 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 }
696}
697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800698/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700699static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700701 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700702 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703
704 switch (channels) {
705 /*
706 * Do not handle stereo output in Multi-channel cases
707 * Stereo case is handled in normal playback path
708 */
709 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700710 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
711 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
712 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
713 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
714 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
715 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800716 break;
717 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700718 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
719 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
720 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
721 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
722 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
723 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
724 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725 break;
726 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700727 ALOGE("HDMI does not support multi channel playback");
728 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800729 break;
730 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700731 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732}
733
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800734audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
735 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700736{
737 struct audio_usecase *usecase;
738 struct listnode *node;
739
740 list_for_each(node, &adev->usecase_list) {
741 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800742 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700743 ALOGV("%s: usecase id %d", __func__, usecase->id);
744 return usecase->id;
745 }
746 }
747 return USECASE_INVALID;
748}
749
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700750struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700751 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700752{
753 struct audio_usecase *usecase;
754 struct listnode *node;
755
756 list_for_each(node, &adev->usecase_list) {
757 usecase = node_to_item(node, struct audio_usecase, list);
758 if (usecase->id == uc_id)
759 return usecase;
760 }
761 return NULL;
762}
763
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700764int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800766 snd_device_t out_snd_device = SND_DEVICE_NONE;
767 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700768 struct audio_usecase *usecase = NULL;
769 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800770 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800771 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800772 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800773 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700774 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700776 usecase = get_usecase_from_list(adev, uc_id);
777 if (usecase == NULL) {
778 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
779 return -EINVAL;
780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800782 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800783 (usecase->type == VOIP_CALL) ||
784 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700785 out_snd_device = platform_get_output_snd_device(adev->platform,
786 usecase->stream.out->devices);
787 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700788 usecase->devices = usecase->stream.out->devices;
789 } else {
790 /*
791 * If the voice call is active, use the sound devices of voice call usecase
792 * so that it would not result any device switch. All the usecases will
793 * be switched to new device when select_devices() is called for voice call
794 * usecase. This is to avoid switching devices for voice call when
795 * check_usecases_codec_backend() is called below.
796 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700797 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700798 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800799 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700800 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
801 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802 in_snd_device = vc_usecase->in_snd_device;
803 out_snd_device = vc_usecase->out_snd_device;
804 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800805 } else if (voice_extn_compress_voip_is_active(adev)) {
806 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700807 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530808 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700809 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800810 in_snd_device = voip_usecase->in_snd_device;
811 out_snd_device = voip_usecase->out_snd_device;
812 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800813 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800814 hfp_ucid = audio_extn_hfp_get_usecase();
815 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700816 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800817 in_snd_device = hfp_usecase->in_snd_device;
818 out_snd_device = hfp_usecase->out_snd_device;
819 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 }
821 if (usecase->type == PCM_PLAYBACK) {
822 usecase->devices = usecase->stream.out->devices;
823 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700824 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700825 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700826 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700827 if (usecase->stream.out == adev->primary_output &&
828 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800829 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
830 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700831 select_devices(adev, adev->active_input->usecase);
832 }
833 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 } else if (usecase->type == PCM_CAPTURE) {
835 usecase->devices = usecase->stream.in->device;
836 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700837 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700838 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530839 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
840 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
841 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
842 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700843 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800844 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700845 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
846 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700847 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700848 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700849 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 }
851 }
852
853 if (out_snd_device == usecase->out_snd_device &&
854 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855 return 0;
856 }
857
sangwoobc677242013-08-08 16:53:43 +0900858 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700859 out_snd_device, platform_get_snd_device_name(out_snd_device),
860 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862 /*
863 * Limitation: While in call, to do a device switch we need to disable
864 * and enable both RX and TX devices though one of them is same as current
865 * device.
866 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700867 if ((usecase->type == VOICE_CALL) &&
868 (usecase->in_snd_device != SND_DEVICE_NONE) &&
869 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700870 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800871 }
872
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 /* Disable current sound devices */
874 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700875 disable_audio_route(adev, usecase);
876 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877 }
878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700880 disable_audio_route(adev, usecase);
881 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800882 }
883
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800884 /* Applicable only on the targets that has external modem.
885 * New device information should be sent to modem before enabling
886 * the devices to reduce in-call device switch time.
887 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700888 if ((usecase->type == VOICE_CALL) &&
889 (usecase->in_snd_device != SND_DEVICE_NONE) &&
890 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800891 status = platform_switch_voice_call_enable_device_config(adev->platform,
892 out_snd_device,
893 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700894 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800895
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 /* Enable new sound devices */
897 if (out_snd_device != SND_DEVICE_NONE) {
898 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
899 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700900 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800901 }
902
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700903 if (in_snd_device != SND_DEVICE_NONE) {
904 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700905 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907
Avinash Vaish71a8b972014-07-24 15:36:33 +0530908 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700909 status = platform_switch_voice_call_device_post(adev->platform,
910 out_snd_device,
911 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530912 enable_audio_route_for_voice_usecases(adev, usecase);
913 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800914
sangwoo170731f2013-06-08 15:36:36 +0900915 usecase->in_snd_device = in_snd_device;
916 usecase->out_snd_device = out_snd_device;
917
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530918 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700919 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530920 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700921 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530922 usecase->stream.out->flags,
923 usecase->stream.out->format,
924 usecase->stream.out->sample_rate,
925 usecase->stream.out->bit_width,
926 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700927 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530928 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700929
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700930 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900931
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800932 /* Applicable only on the targets that has external modem.
933 * Enable device command should be sent to modem only after
934 * enabling voice call mixer controls
935 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700936 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800937 status = platform_switch_voice_call_usecase_route_post(adev->platform,
938 out_snd_device,
939 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530940 ALOGD("%s: done",__func__);
941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800942 return status;
943}
944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945static int stop_input_stream(struct stream_in *in)
946{
947 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948 struct audio_usecase *uc_info;
949 struct audio_device *adev = in->dev;
950
Eric Laurentc8400632013-02-14 19:04:54 -0800951 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952
Eric Laurent994a6932013-07-17 11:51:42 -0700953 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955 uc_info = get_usecase_from_list(adev, in->usecase);
956 if (uc_info == NULL) {
957 ALOGE("%s: Could not find the usecase (%d) in the list",
958 __func__, in->usecase);
959 return -EINVAL;
960 }
961
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800962 /* Close in-call recording streams */
963 voice_check_and_stop_incall_rec_usecase(adev, in);
964
Eric Laurent150dbfe2013-02-27 14:31:02 -0800965 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700966 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967
968 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700969 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800971 list_remove(&uc_info->list);
972 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973
Eric Laurent994a6932013-07-17 11:51:42 -0700974 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975 return ret;
976}
977
978int start_input_stream(struct stream_in *in)
979{
980 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800981 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982 struct audio_usecase *uc_info;
983 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530984 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985
Mingming Yine62d7842013-10-25 16:26:03 -0700986 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530987 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
988 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700989
Naresh Tanniru80659832014-06-04 18:17:56 +0530990
991 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +0530992 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +0530993 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +0530994 goto error_config;
995 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530996
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700997 /* Check if source matches incall recording usecase criteria */
998 ret = voice_check_and_set_incall_rec_usecase(adev, in);
999 if (ret)
1000 goto error_config;
1001 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001002 ALOGD("%s: Updated usecase(%d: %s)",
1003 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001004
Eric Laurentb23d5282013-05-14 15:27:20 -07001005 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006 if (in->pcm_device_id < 0) {
1007 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1008 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001009 ret = -EINVAL;
1010 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001011 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001012
1013 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001015
1016 if (!uc_info) {
1017 ret = -ENOMEM;
1018 goto error_config;
1019 }
1020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 uc_info->id = in->usecase;
1022 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001023 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001024 uc_info->devices = in->device;
1025 uc_info->in_snd_device = SND_DEVICE_NONE;
1026 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001028 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301029 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031
Eric Laurentc8400632013-02-14 19:04:54 -08001032 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001033 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1034
1035 unsigned int flags = PCM_IN;
1036 unsigned int pcm_open_retry_count = 0;
1037
1038 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1039 flags |= PCM_MMAP | PCM_NOIRQ;
1040 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1041 }
1042
1043 while (1) {
1044 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1045 flags, &in->config);
1046 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1047 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1048 if (in->pcm != NULL) {
1049 pcm_close(in->pcm);
1050 in->pcm = NULL;
1051 }
1052 if (pcm_open_retry_count-- == 0) {
1053 ret = -EIO;
1054 goto error_open;
1055 }
1056 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1057 continue;
1058 }
1059 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301061 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301062
Eric Laurent994a6932013-07-17 11:51:42 -07001063 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001064 return ret;
1065
1066error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301068 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001069
1070error_config:
1071 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001073
1074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001077/* must be called with out->lock locked */
1078static int send_offload_cmd_l(struct stream_out* out, int command)
1079{
1080 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1081
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001082 if (!cmd) {
1083 ALOGE("failed to allocate mem for command 0x%x", command);
1084 return -ENOMEM;
1085 }
1086
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001087 ALOGVV("%s %d", __func__, command);
1088
1089 cmd->cmd = command;
1090 list_add_tail(&out->offload_cmd_list, &cmd->node);
1091 pthread_cond_signal(&out->offload_cond);
1092 return 0;
1093}
1094
1095/* must be called iwth out->lock locked */
1096static void stop_compressed_output_l(struct stream_out *out)
1097{
1098 out->offload_state = OFFLOAD_STATE_IDLE;
1099 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001100 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001101 if (out->compr != NULL) {
1102 compress_stop(out->compr);
1103 while (out->offload_thread_blocked) {
1104 pthread_cond_wait(&out->cond, &out->lock);
1105 }
1106 }
1107}
1108
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001109bool is_offload_usecase(audio_usecase_t uc_id)
1110{
1111 unsigned int i;
1112 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1113 if (uc_id == offload_usecases[i])
1114 return true;
1115 }
1116 return false;
1117}
1118
1119static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1120{
1121 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1122 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1123 char value[PROPERTY_VALUE_MAX] = {0};
1124
1125 property_get("audio.offload.multiple.enabled", value, NULL);
1126 if (!(atoi(value) || !strncmp("true", value, 4)))
1127 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1128
1129 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1130 for (i = 0; i < num_usecase; i++) {
1131 if (!(adev->offload_usecases_state & (0x1<<i))) {
1132 adev->offload_usecases_state |= 0x1 << i;
1133 ret = offload_usecases[i];
1134 break;
1135 }
1136 }
1137 ALOGV("%s: offload usecase is %d", __func__, ret);
1138 return ret;
1139}
1140
1141static void free_offload_usecase(struct audio_device *adev,
1142 audio_usecase_t uc_id)
1143{
1144 unsigned int i;
1145 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1146 if (offload_usecases[i] == uc_id) {
1147 adev->offload_usecases_state &= ~(0x1<<i);
1148 break;
1149 }
1150 }
1151 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1152}
1153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001154static void *offload_thread_loop(void *context)
1155{
1156 struct stream_out *out = (struct stream_out *) context;
1157 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001158 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001159
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001160 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1161 set_sched_policy(0, SP_FOREGROUND);
1162 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1163
1164 ALOGV("%s", __func__);
1165 pthread_mutex_lock(&out->lock);
1166 for (;;) {
1167 struct offload_cmd *cmd = NULL;
1168 stream_callback_event_t event;
1169 bool send_callback = false;
1170
1171 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1172 __func__, list_empty(&out->offload_cmd_list),
1173 out->offload_state);
1174 if (list_empty(&out->offload_cmd_list)) {
1175 ALOGV("%s SLEEPING", __func__);
1176 pthread_cond_wait(&out->offload_cond, &out->lock);
1177 ALOGV("%s RUNNING", __func__);
1178 continue;
1179 }
1180
1181 item = list_head(&out->offload_cmd_list);
1182 cmd = node_to_item(item, struct offload_cmd, node);
1183 list_remove(item);
1184
1185 ALOGVV("%s STATE %d CMD %d out->compr %p",
1186 __func__, out->offload_state, cmd->cmd, out->compr);
1187
1188 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1189 free(cmd);
1190 break;
1191 }
1192
1193 if (out->compr == NULL) {
1194 ALOGE("%s: Compress handle is NULL", __func__);
1195 pthread_cond_signal(&out->cond);
1196 continue;
1197 }
1198 out->offload_thread_blocked = true;
1199 pthread_mutex_unlock(&out->lock);
1200 send_callback = false;
1201 switch(cmd->cmd) {
1202 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001203 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001204 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001205 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001206 send_callback = true;
1207 event = STREAM_CBK_EVENT_WRITE_READY;
1208 break;
1209 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001210 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301211 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001212 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301213 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001214 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301215 if (ret < 0)
1216 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301217 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301218 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001219 compress_drain(out->compr);
1220 else
1221 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301222 if (ret != -ENETRESET) {
1223 send_callback = true;
1224 event = STREAM_CBK_EVENT_DRAIN_READY;
1225 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1226 } else
1227 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001228 break;
1229 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001230 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001231 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001232 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001233 send_callback = true;
1234 event = STREAM_CBK_EVENT_DRAIN_READY;
1235 break;
1236 default:
1237 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1238 break;
1239 }
1240 pthread_mutex_lock(&out->lock);
1241 out->offload_thread_blocked = false;
1242 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001243 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001244 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001245 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001246 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001247 free(cmd);
1248 }
1249
1250 pthread_cond_signal(&out->cond);
1251 while (!list_empty(&out->offload_cmd_list)) {
1252 item = list_head(&out->offload_cmd_list);
1253 list_remove(item);
1254 free(node_to_item(item, struct offload_cmd, node));
1255 }
1256 pthread_mutex_unlock(&out->lock);
1257
1258 return NULL;
1259}
1260
1261static int create_offload_callback_thread(struct stream_out *out)
1262{
1263 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1264 list_init(&out->offload_cmd_list);
1265 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1266 offload_thread_loop, out);
1267 return 0;
1268}
1269
1270static int destroy_offload_callback_thread(struct stream_out *out)
1271{
1272 pthread_mutex_lock(&out->lock);
1273 stop_compressed_output_l(out);
1274 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1275
1276 pthread_mutex_unlock(&out->lock);
1277 pthread_join(out->offload_thread, (void **) NULL);
1278 pthread_cond_destroy(&out->offload_cond);
1279
1280 return 0;
1281}
1282
Eric Laurent07eeafd2013-10-06 12:52:49 -07001283static bool allow_hdmi_channel_config(struct audio_device *adev)
1284{
1285 struct listnode *node;
1286 struct audio_usecase *usecase;
1287 bool ret = true;
1288
1289 list_for_each(node, &adev->usecase_list) {
1290 usecase = node_to_item(node, struct audio_usecase, list);
1291 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1292 /*
1293 * If voice call is already existing, do not proceed further to avoid
1294 * disabling/enabling both RX and TX devices, CSD calls, etc.
1295 * Once the voice call done, the HDMI channels can be configured to
1296 * max channels of remaining use cases.
1297 */
1298 if (usecase->id == USECASE_VOICE_CALL) {
1299 ALOGD("%s: voice call is active, no change in HDMI channels",
1300 __func__);
1301 ret = false;
1302 break;
1303 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1304 ALOGD("%s: multi channel playback is active, "
1305 "no change in HDMI channels", __func__);
1306 ret = false;
1307 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001308 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001309 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001310 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1311 ", no change in HDMI channels", __func__,
1312 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001313 ret = false;
1314 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001315 }
1316 }
1317 }
1318 return ret;
1319}
1320
1321static int check_and_set_hdmi_channels(struct audio_device *adev,
1322 unsigned int channels)
1323{
1324 struct listnode *node;
1325 struct audio_usecase *usecase;
1326
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001327 unsigned int supported_channels = platform_edid_get_max_channels(
1328 adev->platform);
1329 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001330 /* Check if change in HDMI channel config is allowed */
1331 if (!allow_hdmi_channel_config(adev))
1332 return 0;
1333
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001334 if (channels > supported_channels)
1335 channels = supported_channels;
1336
Eric Laurent07eeafd2013-10-06 12:52:49 -07001337 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001338 ALOGD("%s: Requested channels are same as current channels(%d)",
1339 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001340 return 0;
1341 }
1342
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001343 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001344 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001345 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001346 adev->cur_hdmi_channels = channels;
1347
1348 /*
1349 * Deroute all the playback streams routed to HDMI so that
1350 * the back end is deactivated. Note that backend will not
1351 * be deactivated if any one stream is connected to it.
1352 */
1353 list_for_each(node, &adev->usecase_list) {
1354 usecase = node_to_item(node, struct audio_usecase, list);
1355 if (usecase->type == PCM_PLAYBACK &&
1356 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001358 }
1359 }
1360
1361 /*
1362 * Enable all the streams disabled above. Now the HDMI backend
1363 * will be activated with new channel configuration
1364 */
1365 list_for_each(node, &adev->usecase_list) {
1366 usecase = node_to_item(node, struct audio_usecase, list);
1367 if (usecase->type == PCM_PLAYBACK &&
1368 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001369 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001370 }
1371 }
1372
1373 return 0;
1374}
1375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376static int stop_output_stream(struct stream_out *out)
1377{
1378 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379 struct audio_usecase *uc_info;
1380 struct audio_device *adev = out->dev;
1381
Eric Laurent994a6932013-07-17 11:51:42 -07001382 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001383 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 uc_info = get_usecase_from_list(adev, out->usecase);
1385 if (uc_info == NULL) {
1386 ALOGE("%s: Could not find the usecase (%d) in the list",
1387 __func__, out->usecase);
1388 return -EINVAL;
1389 }
1390
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001391 if (is_offload_usecase(out->usecase) &&
1392 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001393 if (adev->visualizer_stop_output != NULL)
1394 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001395
1396 audio_extn_dts_remove_state_notifier_node(out->usecase);
1397
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001398 if (adev->offload_effects_stop_output != NULL)
1399 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1400 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001401
Eric Laurent150dbfe2013-02-27 14:31:02 -08001402 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001403 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404
1405 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001406 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001408 list_remove(&uc_info->list);
1409 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001411 if (is_offload_usecase(out->usecase) &&
1412 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1413 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1414 ALOGV("Disable passthrough , reset mixer to pcm");
1415 /* NO_PASSTHROUGH */
1416 out->compr_config.codec->compr_passthr = 0;
1417 audio_extn_dolby_set_hdmi_config(adev, out);
1418 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1419 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001420 /* Must be called after removing the usecase from list */
1421 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1422 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1423
Eric Laurent994a6932013-07-17 11:51:42 -07001424 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 return ret;
1426}
1427
1428int start_output_stream(struct stream_out *out)
1429{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001431 int sink_channels = 0;
1432 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433 struct audio_usecase *uc_info;
1434 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301435 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001437 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1438 ret = -EINVAL;
1439 goto error_config;
1440 }
1441
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301442 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1443 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1444 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301445
Naresh Tanniru80659832014-06-04 18:17:56 +05301446 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301447 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301448 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301449 goto error_config;
1450 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301451
Eric Laurentb23d5282013-05-14 15:27:20 -07001452 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453 if (out->pcm_device_id < 0) {
1454 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1455 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001457 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 }
1459
1460 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001461
1462 if (!uc_info) {
1463 ret = -ENOMEM;
1464 goto error_config;
1465 }
1466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 uc_info->id = out->usecase;
1468 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001469 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 uc_info->devices = out->devices;
1471 uc_info->in_snd_device = SND_DEVICE_NONE;
1472 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001473 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001474 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001475 if (is_offload_usecase(out->usecase)) {
1476 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001477 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1478 }
1479 }
Mingming Yin9c041392014-05-01 15:37:31 -07001480 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1481 if (!strncmp("true", prop_value, 4)) {
1482 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001483 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1484 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001485 check_and_set_hdmi_channels(adev, sink_channels);
1486 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001487 if (is_offload_usecase(out->usecase)) {
1488 unsigned int ch_count = out->compr_config.codec->ch_in;
1489 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1490 /* backend channel config for passthrough stream is stereo */
1491 ch_count = 2;
1492 check_and_set_hdmi_channels(adev, ch_count);
1493 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001494 check_and_set_hdmi_channels(adev, out->config.channels);
1495 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001496 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001497 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001498 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 select_devices(adev, out->usecase);
1501
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001502 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1503 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001504 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001505 unsigned int flags = PCM_OUT;
1506 unsigned int pcm_open_retry_count = 0;
1507 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1508 flags |= PCM_MMAP | PCM_NOIRQ;
1509 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1510 } else
1511 flags |= PCM_MONOTONIC;
1512
1513 while (1) {
1514 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1515 flags, &out->config);
1516 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1517 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1518 if (out->pcm != NULL) {
1519 pcm_close(out->pcm);
1520 out->pcm = NULL;
1521 }
1522 if (pcm_open_retry_count-- == 0) {
1523 ret = -EIO;
1524 goto error_open;
1525 }
1526 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1527 continue;
1528 }
1529 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001530 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001531 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1532 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001533 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001534 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1535 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001537 out->compr = compress_open(adev->snd_card,
1538 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001539 COMPRESS_IN, &out->compr_config);
1540 if (out->compr && !is_compress_ready(out->compr)) {
1541 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1542 compress_close(out->compr);
1543 out->compr = NULL;
1544 ret = -EIO;
1545 goto error_open;
1546 }
1547 if (out->offload_callback)
1548 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001549
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001550 audio_extn_dts_create_state_notifier_node(out->usecase);
1551 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1552 popcount(out->channel_mask),
1553 out->playback_started);
1554
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001555#ifdef DS1_DOLBY_DDP_ENABLED
1556 if (audio_extn_is_dolby_format(out->format))
1557 audio_extn_dolby_send_ddp_endp_params(adev);
1558#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001559 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1560 if (adev->visualizer_start_output != NULL)
1561 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1562 if (adev->offload_effects_start_output != NULL)
1563 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001564 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566 }
Eric Laurent994a6932013-07-17 11:51:42 -07001567 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001569error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001571error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001572 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573}
1574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575static int check_input_parameters(uint32_t sample_rate,
1576 audio_format_t format,
1577 int channel_count)
1578{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001579 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001581 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001582 !voice_extn_compress_voip_is_format_supported(format) &&
1583 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001584
1585 switch (channel_count) {
1586 case 1:
1587 case 2:
1588 case 6:
1589 break;
1590 default:
1591 ret = -EINVAL;
1592 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593
1594 switch (sample_rate) {
1595 case 8000:
1596 case 11025:
1597 case 12000:
1598 case 16000:
1599 case 22050:
1600 case 24000:
1601 case 32000:
1602 case 44100:
1603 case 48000:
1604 break;
1605 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001606 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 }
1608
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001609 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001610}
1611
1612static size_t get_input_buffer_size(uint32_t sample_rate,
1613 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001614 int channel_count,
1615 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001616{
1617 size_t size = 0;
1618
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001619 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1620 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001622 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001623 if (is_low_latency)
1624 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001625 /* ToDo: should use frame_size computed based on the format and
1626 channel_count here. */
1627 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001629 /* make sure the size is multiple of 32 bytes
1630 * At 48 kHz mono 16-bit PCM:
1631 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1632 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1633 */
1634 size += 0x1f;
1635 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001636
1637 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638}
1639
1640static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1641{
1642 struct stream_out *out = (struct stream_out *)stream;
1643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001644 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645}
1646
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001647static int out_set_sample_rate(struct audio_stream *stream __unused,
1648 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649{
1650 return -ENOSYS;
1651}
1652
1653static size_t out_get_buffer_size(const struct audio_stream *stream)
1654{
1655 struct stream_out *out = (struct stream_out *)stream;
1656
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001657 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001659 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1660 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001661
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001662 return out->config.period_size *
1663 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664}
1665
1666static uint32_t out_get_channels(const struct audio_stream *stream)
1667{
1668 struct stream_out *out = (struct stream_out *)stream;
1669
1670 return out->channel_mask;
1671}
1672
1673static audio_format_t out_get_format(const struct audio_stream *stream)
1674{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675 struct stream_out *out = (struct stream_out *)stream;
1676
1677 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001680static int out_set_format(struct audio_stream *stream __unused,
1681 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682{
1683 return -ENOSYS;
1684}
1685
1686static int out_standby(struct audio_stream *stream)
1687{
1688 struct stream_out *out = (struct stream_out *)stream;
1689 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001690
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301691 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1692 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001693 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1694 /* Ignore standby in case of voip call because the voip output
1695 * stream is closed in adev_close_output_stream()
1696 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301697 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001698 return 0;
1699 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001701 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001703 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001705 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001706 if (out->pcm) {
1707 pcm_close(out->pcm);
1708 out->pcm = NULL;
1709 }
1710 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001711 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001712 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001713 out->gapless_mdata.encoder_delay = 0;
1714 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715 if (out->compr != NULL) {
1716 compress_close(out->compr);
1717 out->compr = NULL;
1718 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001719 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001721 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722 }
1723 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001724 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725 return 0;
1726}
1727
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001728static int out_dump(const struct audio_stream *stream __unused,
1729 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730{
1731 return 0;
1732}
1733
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001734static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1735{
1736 int ret = 0;
1737 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001738 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001739 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001740 tmp_mdata.encoder_delay = 0;
1741 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001742 tmp_mdata.min_blk_size = 0;
1743 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001744
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001745 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001746 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001747 return -EINVAL;
1748 }
1749
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001750 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1751 if (ret >= 0) {
1752 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1753 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1754 ALOGV("ADTS format is set in offload mode");
1755 }
1756 out->send_new_metadata = 1;
1757 }
1758
Mingming Yin3ee55c62014-08-04 14:23:35 -07001759 if (out->format == AUDIO_FORMAT_FLAC) {
1760 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1761 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001762 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001763 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1764 out->send_new_metadata = 1;
1765 }
1766 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1767 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001768 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001769 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1770 out->send_new_metadata = 1;
1771 }
1772 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1773 if (ret >= 0) {
1774 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1775 out->send_new_metadata = 1;
1776 }
1777 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1778 if (ret >= 0) {
1779 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1780 out->send_new_metadata = 1;
1781 }
1782 }
1783
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001784 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1785 if(ret >= 0)
1786 is_meta_data_params = true;
1787 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1788 if(ret >= 0 )
1789 is_meta_data_params = true;
1790 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1791 if(ret >= 0 )
1792 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1794 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001795 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001796 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001797 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1799 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001800 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001801 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001802 }
1803
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001804 if(!is_meta_data_params) {
1805 ALOGV("%s: Not gapless meta data params", __func__);
1806 return 0;
1807 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001808 out->gapless_mdata = tmp_mdata;
1809 out->send_new_metadata = 1;
1810 ALOGV("%s new encoder delay %u and padding %u", __func__,
1811 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1812
1813 return 0;
1814}
1815
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001816static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1817{
1818 return out == adev->primary_output || out == adev->voice_tx_output;
1819}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1822{
1823 struct stream_out *out = (struct stream_out *)stream;
1824 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001825 struct audio_usecase *usecase;
1826 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 struct str_parms *parms;
1828 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001829 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001830 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831
sangwoobc677242013-08-08 16:53:43 +09001832 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001833 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301835 if (!parms)
1836 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001837 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1838 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001841 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001843 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301844 * When HDMI cable is unplugged/usb hs is disconnected the
1845 * music playback is paused and the policy manager sends routing=0
1846 * But the audioflingercontinues to write data until standby time
1847 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 * Avoid this by routing audio to speaker until standby.
1849 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301850 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1851 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001853 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1854 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855 }
1856
1857 /*
1858 * select_devices() call below switches all the usecases on the same
1859 * backend to the new device. Refer to check_usecases_codec_backend() in
1860 * the select_devices(). But how do we undo this?
1861 *
1862 * For example, music playback is active on headset (deep-buffer usecase)
1863 * and if we go to ringtones and select a ringtone, low-latency usecase
1864 * will be started on headset+speaker. As we can't enable headset+speaker
1865 * and headset devices at the same time, select_devices() switches the music
1866 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1867 * So when the ringtone playback is completed, how do we undo the same?
1868 *
1869 * We are relying on the out_set_parameters() call on deep-buffer output,
1870 * once the ringtone playback is ended.
1871 * NOTE: We should not check if the current devices are same as new devices.
1872 * Because select_devices() must be called to switch back the music
1873 * playback to headset.
1874 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001875 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 out->devices = val;
1877
1878 if (!out->standby)
1879 select_devices(adev, out->usecase);
1880
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001881 if (output_drives_call(adev, out)) {
1882 if(!voice_is_in_call(adev)) {
1883 if (adev->mode == AUDIO_MODE_IN_CALL) {
1884 adev->current_call_output = out;
1885 ret = voice_start_call(adev);
1886 }
1887 } else {
1888 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001889 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001890 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001891 }
1892 }
1893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001895 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001896 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001897
1898 if (out == adev->primary_output) {
1899 pthread_mutex_lock(&adev->lock);
1900 audio_extn_set_parameters(adev, parms);
1901 pthread_mutex_unlock(&adev->lock);
1902 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001903 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001904 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001905 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001906
1907 audio_extn_dts_create_state_notifier_node(out->usecase);
1908 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1909 popcount(out->channel_mask),
1910 out->playback_started);
1911
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001912 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001913 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301916error:
Eric Laurent994a6932013-07-17 11:51:42 -07001917 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 return ret;
1919}
1920
1921static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1922{
1923 struct stream_out *out = (struct stream_out *)stream;
1924 struct str_parms *query = str_parms_create_str(keys);
1925 char *str;
1926 char value[256];
1927 struct str_parms *reply = str_parms_create();
1928 size_t i, j;
1929 int ret;
1930 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001931
1932 if (!query || !reply) {
1933 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1934 return NULL;
1935 }
1936
Eric Laurent994a6932013-07-17 11:51:42 -07001937 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1939 if (ret >= 0) {
1940 value[0] = '\0';
1941 i = 0;
1942 while (out->supported_channel_masks[i] != 0) {
1943 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1944 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1945 if (!first) {
1946 strcat(value, "|");
1947 }
1948 strcat(value, out_channels_name_to_enum_table[j].name);
1949 first = false;
1950 break;
1951 }
1952 }
1953 i++;
1954 }
1955 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1956 str = str_parms_to_str(reply);
1957 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001958 voice_extn_out_get_parameters(out, query, reply);
1959 str = str_parms_to_str(reply);
1960 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001961 free(str);
1962 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001963 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001965
1966 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1967 if (ret >= 0) {
1968 value[0] = '\0';
1969 i = 0;
1970 first = true;
1971 while (out->supported_formats[i] != 0) {
1972 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1973 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1974 if (!first) {
1975 strcat(value, "|");
1976 }
1977 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1978 first = false;
1979 break;
1980 }
1981 }
1982 i++;
1983 }
1984 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
1985 str = str_parms_to_str(reply);
1986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 str_parms_destroy(query);
1988 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990 return str;
1991}
1992
1993static uint32_t out_get_latency(const struct audio_stream_out *stream)
1994{
1995 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08001996 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997
Alexy Josephaa54c872014-12-03 02:46:47 -08001998 if (is_offload_usecase(out->usecase)) {
1999 if (out->use_small_bufs == true)
2000 latency = ((out->compr_config.fragments *
2001 out->compr_config.fragment_size * 1000) /
2002 (out->sample_rate * out->compr_config.codec->ch_in *
2003 audio_bytes_per_sample(out->format)));
2004 else
2005 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2006 } else {
2007 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002008 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002009 }
2010
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302011 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002012 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013}
2014
2015static int out_set_volume(struct audio_stream_out *stream, float left,
2016 float right)
2017{
Eric Laurenta9024de2013-04-04 09:19:12 -07002018 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 int volume[2];
2020
Eric Laurenta9024de2013-04-04 09:19:12 -07002021 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2022 /* only take left channel into account: the API is for stereo anyway */
2023 out->muted = (left == 0.0f);
2024 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002025 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002026 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2027 /*
2028 * Set mute or umute on HDMI passthrough stream.
2029 * Only take left channel into account.
2030 * Mute is 0 and unmute 1
2031 */
2032 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2033 } else {
2034 char mixer_ctl_name[128];
2035 struct audio_device *adev = out->dev;
2036 struct mixer_ctl *ctl;
2037 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002038 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002040 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2041 "Compress Playback %d Volume", pcm_device_id);
2042 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2043 if (!ctl) {
2044 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2045 __func__, mixer_ctl_name);
2046 return -EINVAL;
2047 }
2048 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2049 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2050 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2051 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002053 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 return -ENOSYS;
2056}
2057
2058static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2059 size_t bytes)
2060{
2061 struct stream_out *out = (struct stream_out *)stream;
2062 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302063 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002064 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302067
Naresh Tanniru80659832014-06-04 18:17:56 +05302068 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2069 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302070 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302071 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302072 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002073 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302074 //during SSR for compress usecase we should return error to flinger
2075 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2076 pthread_mutex_unlock(&out->lock);
2077 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302078 }
2079 }
2080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002082 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002083 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002084 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2085 ret = voice_extn_compress_voip_start_output_stream(out);
2086 else
2087 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002088 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002091 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 goto exit;
2093 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002096 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002097 ALOGD("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002098 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002099 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002100 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2101 out->send_new_metadata = 0;
2102 }
2103
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302105 if (ret < 0)
2106 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002107 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002108 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302109 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302111 } else if (-ENETRESET == ret) {
2112 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2113 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2114 pthread_mutex_unlock(&out->lock);
2115 out_standby(&out->stream.common);
2116 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302118 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 compress_start(out->compr);
2120 out->playback_started = 1;
2121 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002122
2123 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2124 popcount(out->channel_mask),
2125 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 }
2127 pthread_mutex_unlock(&out->lock);
2128 return ret;
2129 } else {
2130 if (out->pcm) {
2131 if (out->muted)
2132 memset((void *)buffer, 0, bytes);
2133 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002134 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2135 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2136 else
2137 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302138 if (ret < 0)
2139 ret = -errno;
2140 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002141 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143 }
2144
2145exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302146 /* ToDo: There may be a corner case when SSR happens back to back during
2147 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302148 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302149 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302150 }
2151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 pthread_mutex_unlock(&out->lock);
2153
2154 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002155 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002156 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302157 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302158 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302159 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302160 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302161 out->standby = true;
2162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002164 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165 out_get_sample_rate(&out->stream.common));
2166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 }
2168 return bytes;
2169}
2170
2171static int out_get_render_position(const struct audio_stream_out *stream,
2172 uint32_t *dsp_frames)
2173{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302175 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002176 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002177 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002178 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002179 pthread_mutex_lock(&out->lock);
2180 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302181 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302183 if (ret < 0)
2184 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 ALOGVV("%s rendered frames %d sample_rate %d",
2186 __func__, *dsp_frames, out->sample_rate);
2187 }
2188 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302189 if (-ENETRESET == ret) {
2190 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2191 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2192 return -EINVAL;
2193 } else if(ret < 0) {
2194 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2195 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302196 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2197 /*
2198 * Handle corner case where compress session is closed during SSR
2199 * and timestamp is queried
2200 */
2201 ALOGE(" ERROR: sound card not active, return error");
2202 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302203 } else {
2204 return 0;
2205 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 } else
2207 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208}
2209
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002210static int out_add_audio_effect(const struct audio_stream *stream __unused,
2211 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212{
2213 return 0;
2214}
2215
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002216static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2217 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218{
2219 return 0;
2220}
2221
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002222static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2223 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224{
2225 return -EINVAL;
2226}
2227
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002228static int out_get_presentation_position(const struct audio_stream_out *stream,
2229 uint64_t *frames, struct timespec *timestamp)
2230{
2231 struct stream_out *out = (struct stream_out *)stream;
2232 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002233 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002234
2235 pthread_mutex_lock(&out->lock);
2236
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002237 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002238 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302239 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002240 &out->sample_rate);
2241 ALOGVV("%s rendered frames %ld sample_rate %d",
2242 __func__, dsp_frames, out->sample_rate);
2243 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302244 if (ret < 0)
2245 ret = -errno;
2246 if (-ENETRESET == ret) {
2247 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2248 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2249 ret = -EINVAL;
2250 } else
2251 ret = 0;
2252
Eric Laurent949a0892013-09-20 09:20:13 -07002253 /* this is the best we can do */
2254 clock_gettime(CLOCK_MONOTONIC, timestamp);
2255 }
2256 } else {
2257 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002258 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002259 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2260 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002261 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002262 // This adjustment accounts for buffering after app processor.
2263 // It is based on estimated DSP latency per use case, rather than exact.
2264 signed_frames -=
2265 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2266
Eric Laurent949a0892013-09-20 09:20:13 -07002267 // It would be unusual for this value to be negative, but check just in case ...
2268 if (signed_frames >= 0) {
2269 *frames = signed_frames;
2270 ret = 0;
2271 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002272 }
2273 }
2274 }
2275
2276 pthread_mutex_unlock(&out->lock);
2277
2278 return ret;
2279}
2280
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002281static int out_set_callback(struct audio_stream_out *stream,
2282 stream_callback_t callback, void *cookie)
2283{
2284 struct stream_out *out = (struct stream_out *)stream;
2285
2286 ALOGV("%s", __func__);
2287 pthread_mutex_lock(&out->lock);
2288 out->offload_callback = callback;
2289 out->offload_cookie = cookie;
2290 pthread_mutex_unlock(&out->lock);
2291 return 0;
2292}
2293
2294static int out_pause(struct audio_stream_out* stream)
2295{
2296 struct stream_out *out = (struct stream_out *)stream;
2297 int status = -ENOSYS;
2298 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002299 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002300 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002301 pthread_mutex_lock(&out->lock);
2302 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302303 struct audio_device *adev = out->dev;
2304 int snd_scard_state = get_snd_card_state(adev);
2305
2306 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2307 status = compress_pause(out->compr);
2308
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002309 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002310
2311 audio_extn_dts_eagle_fade(adev, false);
2312 audio_extn_dts_notify_playback_state(out->usecase, 0,
2313 out->sample_rate, popcount(out->channel_mask),
2314 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 }
2316 pthread_mutex_unlock(&out->lock);
2317 }
2318 return status;
2319}
2320
2321static int out_resume(struct audio_stream_out* stream)
2322{
2323 struct stream_out *out = (struct stream_out *)stream;
2324 int status = -ENOSYS;
2325 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002326 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002327 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002328 status = 0;
2329 pthread_mutex_lock(&out->lock);
2330 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302331 struct audio_device *adev = out->dev;
2332 int snd_scard_state = get_snd_card_state(adev);
2333
2334 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2335 status = compress_resume(out->compr);
2336
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002338
2339 audio_extn_dts_eagle_fade(adev, true);
2340 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2341 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 }
2343 pthread_mutex_unlock(&out->lock);
2344 }
2345 return status;
2346}
2347
2348static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2349{
2350 struct stream_out *out = (struct stream_out *)stream;
2351 int status = -ENOSYS;
2352 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002353 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 pthread_mutex_lock(&out->lock);
2355 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2356 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2357 else
2358 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2359 pthread_mutex_unlock(&out->lock);
2360 }
2361 return status;
2362}
2363
2364static int out_flush(struct audio_stream_out* stream)
2365{
2366 struct stream_out *out = (struct stream_out *)stream;
2367 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002368 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002369 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 pthread_mutex_lock(&out->lock);
2371 stop_compressed_output_l(out);
2372 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002373 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 return 0;
2375 }
2376 return -ENOSYS;
2377}
2378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379/** audio_stream_in implementation **/
2380static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2381{
2382 struct stream_in *in = (struct stream_in *)stream;
2383
2384 return in->config.rate;
2385}
2386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002387static int in_set_sample_rate(struct audio_stream *stream __unused,
2388 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389{
2390 return -ENOSYS;
2391}
2392
2393static size_t in_get_buffer_size(const struct audio_stream *stream)
2394{
2395 struct stream_in *in = (struct stream_in *)stream;
2396
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002397 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2398 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002399 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2400 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002401
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002402 return in->config.period_size *
2403 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404}
2405
2406static uint32_t in_get_channels(const struct audio_stream *stream)
2407{
2408 struct stream_in *in = (struct stream_in *)stream;
2409
2410 return in->channel_mask;
2411}
2412
2413static audio_format_t in_get_format(const struct audio_stream *stream)
2414{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002415 struct stream_in *in = (struct stream_in *)stream;
2416
2417 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418}
2419
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002420static int in_set_format(struct audio_stream *stream __unused,
2421 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422{
2423 return -ENOSYS;
2424}
2425
2426static int in_standby(struct audio_stream *stream)
2427{
2428 struct stream_in *in = (struct stream_in *)stream;
2429 struct audio_device *adev = in->dev;
2430 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302431 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2432 stream, in->usecase, use_case_table[in->usecase]);
2433
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002434 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2435 /* Ignore standby in case of voip call because the voip input
2436 * stream is closed in adev_close_input_stream()
2437 */
2438 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2439 return status;
2440 }
2441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002443 if (!in->standby && in->is_st_session) {
2444 ALOGD("%s: sound trigger pcm stop lab", __func__);
2445 audio_extn_sound_trigger_stop_lab(in);
2446 in->standby = 1;
2447 }
2448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002450 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002452 if (in->pcm) {
2453 pcm_close(in->pcm);
2454 in->pcm = NULL;
2455 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002457 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458 }
2459 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002460 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461 return status;
2462}
2463
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002464static int in_dump(const struct audio_stream *stream __unused,
2465 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466{
2467 return 0;
2468}
2469
2470static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2471{
2472 struct stream_in *in = (struct stream_in *)stream;
2473 struct audio_device *adev = in->dev;
2474 struct str_parms *parms;
2475 char *str;
2476 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002477 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302479 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 parms = str_parms_create_str(kvpairs);
2481
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302482 if (!parms)
2483 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002485 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002486
2487 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2488 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 val = atoi(value);
2490 /* no audio source uses val == 0 */
2491 if ((in->source != val) && (val != 0)) {
2492 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002493 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2494 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2495 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2496 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002497 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002498 err = voice_extn_compress_voip_open_input_stream(in);
2499 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002500 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002501 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002502 }
2503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 }
2505 }
2506
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002507 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2508 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002510 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 in->device = val;
2512 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002513 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002514 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 }
2516 }
2517
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002518done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002520 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
2522 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302523error:
Eric Laurent994a6932013-07-17 11:51:42 -07002524 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 return ret;
2526}
2527
2528static char* in_get_parameters(const struct audio_stream *stream,
2529 const char *keys)
2530{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002531 struct stream_in *in = (struct stream_in *)stream;
2532 struct str_parms *query = str_parms_create_str(keys);
2533 char *str;
2534 char value[256];
2535 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002536
2537 if (!query || !reply) {
2538 ALOGE("in_get_parameters: failed to create query or reply");
2539 return NULL;
2540 }
2541
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002542 ALOGV("%s: enter: keys - %s", __func__, keys);
2543
2544 voice_extn_in_get_parameters(in, query, reply);
2545
2546 str = str_parms_to_str(reply);
2547 str_parms_destroy(query);
2548 str_parms_destroy(reply);
2549
2550 ALOGV("%s: exit: returns - %s", __func__, str);
2551 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552}
2553
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002554static int in_set_gain(struct audio_stream_in *stream __unused,
2555 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556{
2557 return 0;
2558}
2559
2560static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2561 size_t bytes)
2562{
2563 struct stream_in *in = (struct stream_in *)stream;
2564 struct audio_device *adev = in->dev;
2565 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302566 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302569
2570 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302571 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302572 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302573 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302574 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002575 } else {
2576 if (in->is_st_session && !in->is_st_session_active) {
2577 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2578 ret= -EIO;;
2579 goto exit;
2580 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302581 }
2582 }
2583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002585 if (!in->is_st_session) {
2586 pthread_mutex_lock(&adev->lock);
2587 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2588 ret = voice_extn_compress_voip_start_input_stream(in);
2589 else
2590 ret = start_input_stream(in);
2591 pthread_mutex_unlock(&adev->lock);
2592 if (ret != 0) {
2593 goto exit;
2594 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 }
2596 in->standby = 0;
2597 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598
2599 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002600 if (audio_extn_ssr_get_enabled() &&
2601 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002602 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002603 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2604 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002605 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2606 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002607 else
2608 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302609 if (ret < 0)
2610 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
2612
2613 /*
2614 * Instead of writing zeroes here, we could trust the hardware
2615 * to always provide zeroes when muted.
2616 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302617 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2618 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 memset(buffer, 0, bytes);
2620
2621exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302622 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302623 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002625 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2626 session reading on LAB data. In this case do not set sound card state
2627 offline, instead mark this sound trigger session inactive to avoid
2628 further reading of LAB data from CPE driver. Marking the session
2629 inactive handles both CPE and ADSP SSR for sound trigger session */
2630 if (!in->is_st_session)
2631 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2632 else
2633 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 pthread_mutex_unlock(&in->lock);
2636
2637 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302638 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302639 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302640 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302641 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302642 in->standby = true;
2643 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302644 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002646 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002647 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302648 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 }
2650 return bytes;
2651}
2652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002653static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654{
2655 return 0;
2656}
2657
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002658static int add_remove_audio_effect(const struct audio_stream *stream,
2659 effect_handle_t effect,
2660 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002662 struct stream_in *in = (struct stream_in *)stream;
2663 int status = 0;
2664 effect_descriptor_t desc;
2665
2666 status = (*effect)->get_descriptor(effect, &desc);
2667 if (status != 0)
2668 return status;
2669
2670 pthread_mutex_lock(&in->lock);
2671 pthread_mutex_lock(&in->dev->lock);
2672 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2673 in->enable_aec != enable &&
2674 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2675 in->enable_aec = enable;
2676 if (!in->standby)
2677 select_devices(in->dev, in->usecase);
2678 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002679 if (in->enable_ns != enable &&
2680 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2681 in->enable_ns = enable;
2682 if (!in->standby)
2683 select_devices(in->dev, in->usecase);
2684 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002685 pthread_mutex_unlock(&in->dev->lock);
2686 pthread_mutex_unlock(&in->lock);
2687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 return 0;
2689}
2690
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002691static int in_add_audio_effect(const struct audio_stream *stream,
2692 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693{
Eric Laurent994a6932013-07-17 11:51:42 -07002694 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002695 return add_remove_audio_effect(stream, effect, true);
2696}
2697
2698static int in_remove_audio_effect(const struct audio_stream *stream,
2699 effect_handle_t effect)
2700{
Eric Laurent994a6932013-07-17 11:51:42 -07002701 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002702 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703}
2704
2705static int adev_open_output_stream(struct audio_hw_device *dev,
2706 audio_io_handle_t handle,
2707 audio_devices_t devices,
2708 audio_output_flags_t flags,
2709 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002710 struct audio_stream_out **stream_out,
2711 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712{
2713 struct audio_device *adev = (struct audio_device *)dev;
2714 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002715 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002716 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302719
2720 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2721 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2722 ALOGE(" sound card is not active rejecting compress output open request");
2723 return -EINVAL;
2724 }
2725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2727
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302728 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2729 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2730 devices, flags, &out->stream);
2731
2732
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002733 if (!out) {
2734 return -ENOMEM;
2735 }
2736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 if (devices == AUDIO_DEVICE_NONE)
2738 devices = AUDIO_DEVICE_OUT_SPEAKER;
2739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 out->flags = flags;
2741 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002742 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002743 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 out->sample_rate = config->sample_rate;
2745 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2746 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002747 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002748 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002749 out->non_blocking = 0;
2750 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751
2752 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002753 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2754 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2755 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2756
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002757 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002758 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2759 ret = read_hdmi_channel_masks(out);
2760
2761 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2762 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002763 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002764 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002765 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002766
2767 if (config->sample_rate == 0)
2768 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2769 if (config->channel_mask == 0)
2770 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2771
2772 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002773 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2775 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002777 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002779 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2780 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002781 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002782 ret = voice_extn_compress_voip_open_output_stream(out);
2783 if (ret != 0) {
2784 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2785 __func__, ret);
2786 goto error_open;
2787 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002788 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2789 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2790 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2791 ALOGE("%s: Unsupported Offload information", __func__);
2792 ret = -EINVAL;
2793 goto error_open;
2794 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002795
2796 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2797 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2798 ALOGV("read and update_pass through formats");
2799 ret = audio_extn_dolby_update_passt_formats(adev, out);
2800 if(ret != 0) {
2801 goto error_open;
2802 }
2803 if(config->offload_info.format == 0)
2804 config->offload_info.format = out->supported_formats[0];
2805 }
2806
Mingming Yin90310102013-11-13 16:57:00 -08002807 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002808 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 ALOGE("%s: Unsupported audio format", __func__);
2810 ret = -EINVAL;
2811 goto error_open;
2812 }
2813
2814 out->compr_config.codec = (struct snd_codec *)
2815 calloc(1, sizeof(struct snd_codec));
2816
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002817 if (!out->compr_config.codec) {
2818 ret = -ENOMEM;
2819 goto error_open;
2820 }
2821
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002822 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 if (config->offload_info.channel_mask)
2824 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002825 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002827 config->offload_info.channel_mask = config->channel_mask;
2828 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002829 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 out->sample_rate = config->offload_info.sample_rate;
2831
2832 out->stream.set_callback = out_set_callback;
2833 out->stream.pause = out_pause;
2834 out->stream.resume = out_resume;
2835 out->stream.drain = out_drain;
2836 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002837 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002839 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002840 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002841 audio_extn_dolby_get_snd_codec_id(adev, out,
2842 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002843 else
2844 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002846 if (audio_is_offload_pcm(config->offload_info.format)) {
2847 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002848 platform_get_pcm_offload_buffer_size(&config->offload_info);
2849 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2850 out->compr_config.fragment_size =
2851 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002852 } else {
2853 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002854 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002855 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2857 out->compr_config.codec->sample_rate =
2858 compress_get_alsa_rate(config->offload_info.sample_rate);
2859 out->compr_config.codec->bit_rate =
2860 config->offload_info.bit_rate;
2861 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002862 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002864 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002865 /*TODO: Do we need to change it for passthrough */
2866 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002867
Mingming Yin3ee55c62014-08-04 14:23:35 -07002868 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2869 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002870 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2871 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002872 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002873 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2874
Mingming Yin3ee55c62014-08-04 14:23:35 -07002875 if (out->bit_width == 24) {
2876 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2877 }
2878
Amit Shekhar6f461b12014-08-01 14:52:58 -07002879 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002880 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002881
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2883 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002884
Alexy Josephaa54c872014-12-03 02:46:47 -08002885 if (config->offload_info.use_small_bufs) {
2886 //this flag is set from framework only if its for PCM formats
2887 //no need to check for PCM format again
2888 out->non_blocking = 0;
2889 out->use_small_bufs = true;
2890 ALOGI("Keep write blocking for small buff: non_blockling %d",
2891 out->non_blocking);
2892 }
2893
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002894 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002895 out->offload_state = OFFLOAD_STATE_IDLE;
2896 out->playback_started = 0;
2897
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002898 audio_extn_dts_create_state_notifier_node(out->usecase);
2899
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 create_offload_callback_thread(out);
2901 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2902 __func__, config->offload_info.version,
2903 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002904 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002905 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002906 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2907 ret = voice_check_and_set_incall_music_usecase(adev, out);
2908 if (ret != 0) {
2909 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2910 __func__, ret);
2911 goto error_open;
2912 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002913 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2914 if (config->sample_rate == 0)
2915 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2916 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2917 config->sample_rate != 8000) {
2918 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2919 ret = -EINVAL;
2920 goto error_open;
2921 }
2922 out->sample_rate = config->sample_rate;
2923 out->config.rate = config->sample_rate;
2924 if (config->format == AUDIO_FORMAT_DEFAULT)
2925 config->format = AUDIO_FORMAT_PCM_16_BIT;
2926 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2927 config->format = AUDIO_FORMAT_PCM_16_BIT;
2928 ret = -EINVAL;
2929 goto error_open;
2930 }
2931 out->format = config->format;
2932 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2933 out->config = pcm_config_afe_proxy_playback;
2934 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002935 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002936 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2938 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002939 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002940 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002941 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002942 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002943 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002944 out->config = pcm_config_deep_buffer;
2945 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002946 }
2947
Amit Shekhar1d896042014-10-03 13:16:09 -07002948 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2949 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002950 /* TODO remove this hardcoding and check why width is zero*/
2951 if (out->bit_width == 0)
2952 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002953 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2954 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002955 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002956 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002957 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2958 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2959 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002960 if(adev->primary_output == NULL)
2961 adev->primary_output = out;
2962 else {
2963 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002964 ret = -EEXIST;
2965 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002966 }
2967 }
2968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 /* Check if this usecase is already existing */
2970 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002971 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2972 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002975 ret = -EEXIST;
2976 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 }
2978 pthread_mutex_unlock(&adev->lock);
2979
2980 out->stream.common.get_sample_rate = out_get_sample_rate;
2981 out->stream.common.set_sample_rate = out_set_sample_rate;
2982 out->stream.common.get_buffer_size = out_get_buffer_size;
2983 out->stream.common.get_channels = out_get_channels;
2984 out->stream.common.get_format = out_get_format;
2985 out->stream.common.set_format = out_set_format;
2986 out->stream.common.standby = out_standby;
2987 out->stream.common.dump = out_dump;
2988 out->stream.common.set_parameters = out_set_parameters;
2989 out->stream.common.get_parameters = out_get_parameters;
2990 out->stream.common.add_audio_effect = out_add_audio_effect;
2991 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2992 out->stream.get_latency = out_get_latency;
2993 out->stream.set_volume = out_set_volume;
2994 out->stream.write = out_write;
2995 out->stream.get_render_position = out_get_render_position;
2996 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002997 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003000 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003001 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003003 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3004 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 config->format = out->stream.common.get_format(&out->stream.common);
3007 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3008 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3009
3010 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303011 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3012 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003013
3014 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3015 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3016 popcount(out->channel_mask), out->playback_started);
3017
Eric Laurent994a6932013-07-17 11:51:42 -07003018 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003020
3021error_open:
3022 free(out);
3023 *stream_out = NULL;
3024 ALOGD("%s: exit: ret %d", __func__, ret);
3025 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026}
3027
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003028static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 struct audio_stream_out *stream)
3030{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003031 struct stream_out *out = (struct stream_out *)stream;
3032 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003033 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303035 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3036
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003037 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303038 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003039 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303040 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003041 if(ret != 0)
3042 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3043 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003044 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003045 out_standby(&stream->common);
3046
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003047 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003048 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003050 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 if (out->compr_config.codec != NULL)
3052 free(out->compr_config.codec);
3053 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003054
3055 if (adev->voice_tx_output == out)
3056 adev->voice_tx_output = NULL;
3057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058 pthread_cond_destroy(&out->cond);
3059 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003061 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062}
3063
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003064static void close_compress_sessions(struct audio_device *adev)
3065{
3066 struct stream_out *out = NULL;
3067 struct listnode *node = NULL;
3068 struct listnode *tmp = NULL;
3069 struct audio_usecase *usecase = NULL;
3070 pthread_mutex_lock(&adev->lock);
3071 list_for_each_safe(node, tmp, &adev->usecase_list) {
3072 usecase = node_to_item(node, struct audio_usecase, list);
3073 if (is_offload_usecase(usecase->id)) {
3074 if (usecase && usecase->stream.out) {
3075 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3076 out = usecase->stream.out;
3077 pthread_mutex_unlock(&adev->lock);
3078 out_standby(&out->stream.common);
3079 pthread_mutex_lock(&adev->lock);
3080 }
3081 }
3082 }
3083 pthread_mutex_unlock(&adev->lock);
3084}
3085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3087{
3088 struct audio_device *adev = (struct audio_device *)dev;
3089 struct str_parms *parms;
3090 char *str;
3091 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003092 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003093 int ret;
3094 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003096 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303099 if (!parms)
3100 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003101 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3102 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303103 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303104 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303105 struct listnode *node;
3106 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303107 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303108 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003109 //close compress sessions on OFFLINE status
3110 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303111 } else if (strstr(snd_card_status, "ONLINE")) {
3112 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303113 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303114 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303115 }
3116
3117 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003118 status = voice_set_parameters(adev, parms);
3119 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003120 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003122 status = platform_set_parameters(adev->platform, parms);
3123 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003124 goto done;
3125
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003126 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3127 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003128 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3130 adev->bluetooth_nrec = true;
3131 else
3132 adev->bluetooth_nrec = false;
3133 }
3134
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003135 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3136 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3138 adev->screen_off = false;
3139 else
3140 adev->screen_off = true;
3141 }
3142
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003143 ret = str_parms_get_int(parms, "rotation", &val);
3144 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003145 bool reverse_speakers = false;
3146 switch(val) {
3147 // FIXME: note that the code below assumes that the speakers are in the correct placement
3148 // relative to the user when the device is rotated 90deg from its default rotation. This
3149 // assumption is device-specific, not platform-specific like this code.
3150 case 270:
3151 reverse_speakers = true;
3152 break;
3153 case 0:
3154 case 90:
3155 case 180:
3156 break;
3157 default:
3158 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003159 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003160 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003161 if (status == 0) {
3162 if (adev->speaker_lr_swap != reverse_speakers) {
3163 adev->speaker_lr_swap = reverse_speakers;
3164 // only update the selected device if there is active pcm playback
3165 struct audio_usecase *usecase;
3166 struct listnode *node;
3167 list_for_each(node, &adev->usecase_list) {
3168 usecase = node_to_item(node, struct audio_usecase, list);
3169 if (usecase->type == PCM_PLAYBACK) {
3170 select_devices(adev, usecase->id);
3171 break;
3172 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003173 }
3174 }
3175 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003176 }
3177
Mingming Yin514a8bc2014-07-29 15:22:21 -07003178 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3179 if (ret >= 0) {
3180 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3181 adev->bt_wb_speech_enabled = true;
3182 else
3183 adev->bt_wb_speech_enabled = false;
3184 }
3185
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003186 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3187 if (ret >= 0) {
3188 val = atoi(value);
3189 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3190 ALOGV("cache new edid");
3191 platform_cache_edid(adev->platform);
3192 }
3193 }
3194
3195 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3196 if (ret >= 0) {
3197 val = atoi(value);
3198 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3199 ALOGV("invalidate cached edid");
3200 platform_invalidate_edid(adev->platform);
3201 }
3202 }
3203
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003204 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003205
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003206done:
3207 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003208 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303209error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003210 ALOGV("%s: exit with code(%d)", __func__, status);
3211 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212}
3213
3214static char* adev_get_parameters(const struct audio_hw_device *dev,
3215 const char *keys)
3216{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003217 struct audio_device *adev = (struct audio_device *)dev;
3218 struct str_parms *reply = str_parms_create();
3219 struct str_parms *query = str_parms_create_str(keys);
3220 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303221 char value[256] = {0};
3222 int ret = 0;
3223
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003224 if (!query || !reply) {
3225 ALOGE("adev_get_parameters: failed to create query or reply");
3226 return NULL;
3227 }
3228
Naresh Tannirud7205b62014-06-20 02:54:48 +05303229 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3230 sizeof(value));
3231 if (ret >=0) {
3232 int val = 1;
3233 pthread_mutex_lock(&adev->snd_card_status.lock);
3234 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3235 val = 0;
3236 pthread_mutex_unlock(&adev->snd_card_status.lock);
3237 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3238 goto exit;
3239 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003240
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003241 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003242 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003243 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003244 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303245 pthread_mutex_unlock(&adev->lock);
3246
Naresh Tannirud7205b62014-06-20 02:54:48 +05303247exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003248 str = str_parms_to_str(reply);
3249 str_parms_destroy(query);
3250 str_parms_destroy(reply);
3251
3252 ALOGV("%s: exit: returns - %s", __func__, str);
3253 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254}
3255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003256static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257{
3258 return 0;
3259}
3260
3261static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3262{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003263 int ret;
3264 struct audio_device *adev = (struct audio_device *)dev;
3265 pthread_mutex_lock(&adev->lock);
3266 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003267 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003268 pthread_mutex_unlock(&adev->lock);
3269 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270}
3271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003272static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3273 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274{
3275 return -ENOSYS;
3276}
3277
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003278static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3279 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280{
3281 return -ENOSYS;
3282}
3283
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003284static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3285 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286{
3287 return -ENOSYS;
3288}
3289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003290static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3291 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292{
3293 return -ENOSYS;
3294}
3295
3296static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3297{
3298 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 pthread_mutex_lock(&adev->lock);
3301 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003302 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003304 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3305 voice_is_in_call(adev)) {
3306 voice_stop_call(adev);
3307 adev->current_call_output = NULL;
3308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 }
3310 pthread_mutex_unlock(&adev->lock);
3311 return 0;
3312}
3313
3314static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3315{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003316 int ret;
3317
3318 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003319 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003320 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3321 pthread_mutex_unlock(&adev->lock);
3322
3323 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324}
3325
3326static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3327{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003328 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 return 0;
3330}
3331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003332static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 const struct audio_config *config)
3334{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003335 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003337 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3338 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339}
3340
3341static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003342 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 audio_devices_t devices,
3344 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003345 struct audio_stream_in **stream_in,
3346 audio_input_flags_t flags __unused,
3347 const char *address __unused,
3348 audio_source_t source __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 struct audio_device *adev = (struct audio_device *)dev;
3351 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003352 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003353 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003354 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 *stream_in = NULL;
3357 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3358 return -EINVAL;
3359
3360 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003361
3362 if (!in) {
3363 ALOGE("failed to allocate input stream");
3364 return -ENOMEM;
3365 }
3366
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303367 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003368 stream_handle(%p) io_handle(%d)",__func__, config->sample_rate, config->channel_mask,
3369 devices, &in->stream, handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003371 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 in->stream.common.get_sample_rate = in_get_sample_rate;
3374 in->stream.common.set_sample_rate = in_set_sample_rate;
3375 in->stream.common.get_buffer_size = in_get_buffer_size;
3376 in->stream.common.get_channels = in_get_channels;
3377 in->stream.common.get_format = in_get_format;
3378 in->stream.common.set_format = in_set_format;
3379 in->stream.common.standby = in_standby;
3380 in->stream.common.dump = in_dump;
3381 in->stream.common.set_parameters = in_set_parameters;
3382 in->stream.common.get_parameters = in_get_parameters;
3383 in->stream.common.add_audio_effect = in_add_audio_effect;
3384 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3385 in->stream.set_gain = in_set_gain;
3386 in->stream.read = in_read;
3387 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3388
3389 in->device = devices;
3390 in->source = AUDIO_SOURCE_DEFAULT;
3391 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 in->standby = 1;
3393 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003394 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395
3396 /* Update config params with the requested sample rate and channels */
3397 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003398 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3399 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3400 is_low_latency = true;
3401#if LOW_LATENCY_CAPTURE_USE_CASE
3402 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3403#endif
3404 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003407 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003409 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303410 if (adev->mode != AUDIO_MODE_IN_CALL) {
3411 ret = -EINVAL;
3412 goto err_open;
3413 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003414 if (config->sample_rate == 0)
3415 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3416 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3417 config->sample_rate != 8000) {
3418 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3419 ret = -EINVAL;
3420 goto err_open;
3421 }
3422 if (config->format == AUDIO_FORMAT_DEFAULT)
3423 config->format = AUDIO_FORMAT_PCM_16_BIT;
3424 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3425 config->format = AUDIO_FORMAT_PCM_16_BIT;
3426 ret = -EINVAL;
3427 goto err_open;
3428 }
3429
3430 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3431 in->config = pcm_config_afe_proxy_record;
3432 in->config.channels = channel_count;
3433 in->config.rate = config->sample_rate;
3434 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003435 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003436 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003437 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3438 ret = -EINVAL;
3439 goto err_open;
3440 }
3441 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003442 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003443 }
Mingming Yine62d7842013-10-25 16:26:03 -07003444 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003445 audio_extn_compr_cap_format_supported(config->format) &&
3446 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003447 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003448 } else {
3449 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003450 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003451 buffer_size = get_input_buffer_size(config->sample_rate,
3452 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003453 channel_count,
3454 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003455 in->config.period_size = buffer_size / frame_size;
3456 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003458 /* This stream could be for sound trigger lab,
3459 get sound trigger pcm if present */
3460 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303461 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003464 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003465 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466
3467err_open:
3468 free(in);
3469 *stream_in = NULL;
3470 return ret;
3471}
3472
3473static void adev_close_input_stream(struct audio_hw_device *dev,
3474 struct audio_stream_in *stream)
3475{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003476 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003477 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003478 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303479
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303480 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003481
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303482 /* Disable echo reference while closing input stream */
3483 platform_set_echo_reference(adev->platform, false);
3484
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003485 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303486 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003487 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303488 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003489 if (ret != 0)
3490 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3491 __func__, ret);
3492 } else
3493 in_standby(&stream->common);
3494
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003495 if (audio_extn_ssr_get_enabled() &&
3496 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003497 audio_extn_ssr_deinit();
3498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499
Mingming Yine62d7842013-10-25 16:26:03 -07003500 if(audio_extn_compr_cap_enabled() &&
3501 audio_extn_compr_cap_format_supported(in->config.format))
3502 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003503
3504 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 return;
3506}
3507
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003508static int adev_dump(const audio_hw_device_t *device __unused,
3509 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
3511 return 0;
3512}
3513
3514static int adev_close(hw_device_t *device)
3515{
3516 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003517
3518 if (!adev)
3519 return 0;
3520
3521 pthread_mutex_lock(&adev_init_lock);
3522
3523 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003524 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003525 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003526 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003527 audio_route_free(adev->audio_route);
3528 free(adev->snd_dev_ref_cnt);
3529 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003530 free(device);
3531 adev = NULL;
3532 }
3533 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 return 0;
3535}
3536
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003537/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3538 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3539 * just that it _might_ work.
3540 */
3541static int period_size_is_plausible_for_low_latency(int period_size)
3542{
3543 switch (period_size) {
3544 case 160:
3545 case 240:
3546 case 320:
3547 case 480:
3548 return 1;
3549 default:
3550 return 0;
3551 }
3552}
3553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554static int adev_open(const hw_module_t *module, const char *name,
3555 hw_device_t **device)
3556{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003557 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003559 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3561
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003562 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003563 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003564 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003565 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003566 ALOGD("%s: returning existing instance of adev", __func__);
3567 ALOGD("%s: exit", __func__);
3568 pthread_mutex_unlock(&adev_init_lock);
3569 return 0;
3570 }
3571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572 adev = calloc(1, sizeof(struct audio_device));
3573
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003574 if (!adev) {
3575 pthread_mutex_unlock(&adev_init_lock);
3576 return -ENOMEM;
3577 }
3578
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003579 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3582 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3583 adev->device.common.module = (struct hw_module_t *)module;
3584 adev->device.common.close = adev_close;
3585
3586 adev->device.init_check = adev_init_check;
3587 adev->device.set_voice_volume = adev_set_voice_volume;
3588 adev->device.set_master_volume = adev_set_master_volume;
3589 adev->device.get_master_volume = adev_get_master_volume;
3590 adev->device.set_master_mute = adev_set_master_mute;
3591 adev->device.get_master_mute = adev_get_master_mute;
3592 adev->device.set_mode = adev_set_mode;
3593 adev->device.set_mic_mute = adev_set_mic_mute;
3594 adev->device.get_mic_mute = adev_get_mic_mute;
3595 adev->device.set_parameters = adev_set_parameters;
3596 adev->device.get_parameters = adev_get_parameters;
3597 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3598 adev->device.open_output_stream = adev_open_output_stream;
3599 adev->device.close_output_stream = adev_close_output_stream;
3600 adev->device.open_input_stream = adev_open_input_stream;
3601 adev->device.close_input_stream = adev_close_input_stream;
3602 adev->device.dump = adev_dump;
3603
3604 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003606 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003607 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003610 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003611 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003612 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3613 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003614 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003615 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003616 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003617 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003618 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303619
3620 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3621 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003623 adev->platform = platform_init(adev);
3624 if (!adev->platform) {
3625 free(adev->snd_dev_ref_cnt);
3626 free(adev);
3627 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3628 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003629 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003630 return -EINVAL;
3631 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003632
Naresh Tanniru4c630392014-05-12 01:05:52 +05303633 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3634
Eric Laurentc4aef752013-09-12 17:45:53 -07003635 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3636 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3637 if (adev->visualizer_lib == NULL) {
3638 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3639 } else {
3640 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3641 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003642 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003643 "visualizer_hal_start_output");
3644 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003645 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003646 "visualizer_hal_stop_output");
3647 }
3648 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003649 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003650 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003651
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003652 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3653 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3654 if (adev->offload_effects_lib == NULL) {
3655 ALOGE("%s: DLOPEN failed for %s", __func__,
3656 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3657 } else {
3658 ALOGV("%s: DLOPEN successful for %s", __func__,
3659 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3660 adev->offload_effects_start_output =
3661 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3662 "offload_effects_bundle_hal_start_output");
3663 adev->offload_effects_stop_output =
3664 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3665 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003666 adev->offload_effects_set_hpx_state =
3667 (int (*)(bool))dlsym(adev->offload_effects_lib,
3668 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003669 }
3670 }
3671
Mingming Yin514a8bc2014-07-29 15:22:21 -07003672 adev->bt_wb_speech_enabled = false;
3673
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003674 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 *device = &adev->device.common;
3676
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003677 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3678 &adev->streams_output_cfg_list);
3679
Kiran Kandi910e1862013-10-29 13:29:42 -07003680 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003681
3682 char value[PROPERTY_VALUE_MAX];
3683 int trial;
3684 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3685 trial = atoi(value);
3686 if (period_size_is_plausible_for_low_latency(trial)) {
3687 pcm_config_low_latency.period_size = trial;
3688 pcm_config_low_latency.start_threshold = trial / 4;
3689 pcm_config_low_latency.avail_min = trial / 4;
3690 configured_low_latency_capture_period_size = trial;
3691 }
3692 }
3693 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3694 trial = atoi(value);
3695 if (period_size_is_plausible_for_low_latency(trial)) {
3696 configured_low_latency_capture_period_size = trial;
3697 }
3698 }
3699
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003700 pthread_mutex_unlock(&adev_init_lock);
3701
Eric Laurent994a6932013-07-17 11:51:42 -07003702 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 return 0;
3704}
3705
3706static struct hw_module_methods_t hal_module_methods = {
3707 .open = adev_open,
3708};
3709
3710struct audio_module HAL_MODULE_INFO_SYM = {
3711 .common = {
3712 .tag = HARDWARE_MODULE_TAG,
3713 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3714 .hal_api_version = HARDWARE_HAL_API_VERSION,
3715 .id = AUDIO_HARDWARE_MODULE_ID,
3716 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003717 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 .methods = &hal_module_methods,
3719 },
3720};