blob: a72ae38eda1d3b84b775da1ace90f54593c671e6 [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
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700734static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
735{
736 struct audio_usecase *usecase;
737 struct listnode *node;
738
739 list_for_each(node, &adev->usecase_list) {
740 usecase = node_to_item(node, struct audio_usecase, list);
741 if (usecase->type == VOICE_CALL) {
742 ALOGV("%s: usecase id %d", __func__, usecase->id);
743 return usecase->id;
744 }
745 }
746 return USECASE_INVALID;
747}
748
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700749struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700750 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751{
752 struct audio_usecase *usecase;
753 struct listnode *node;
754
755 list_for_each(node, &adev->usecase_list) {
756 usecase = node_to_item(node, struct audio_usecase, list);
757 if (usecase->id == uc_id)
758 return usecase;
759 }
760 return NULL;
761}
762
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700763int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800764{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800765 snd_device_t out_snd_device = SND_DEVICE_NONE;
766 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700767 struct audio_usecase *usecase = NULL;
768 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800769 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800770 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800771 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800772 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700773 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700775 usecase = get_usecase_from_list(adev, uc_id);
776 if (usecase == NULL) {
777 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
778 return -EINVAL;
779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800780
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800781 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800782 (usecase->type == VOIP_CALL) ||
783 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700784 out_snd_device = platform_get_output_snd_device(adev->platform,
785 usecase->stream.out->devices);
786 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 usecase->devices = usecase->stream.out->devices;
788 } else {
789 /*
790 * If the voice call is active, use the sound devices of voice call usecase
791 * so that it would not result any device switch. All the usecases will
792 * be switched to new device when select_devices() is called for voice call
793 * usecase. This is to avoid switching devices for voice call when
794 * check_usecases_codec_backend() is called below.
795 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700796 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700797 vc_usecase = get_usecase_from_list(adev,
798 get_voice_usecase_id_from_list(adev));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700799 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
800 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700801 in_snd_device = vc_usecase->in_snd_device;
802 out_snd_device = vc_usecase->out_snd_device;
803 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800804 } else if (voice_extn_compress_voip_is_active(adev)) {
805 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700806 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530807 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700808 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800809 in_snd_device = voip_usecase->in_snd_device;
810 out_snd_device = voip_usecase->out_snd_device;
811 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800812 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800813 hfp_ucid = audio_extn_hfp_get_usecase();
814 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700815 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800816 in_snd_device = hfp_usecase->in_snd_device;
817 out_snd_device = hfp_usecase->out_snd_device;
818 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 }
820 if (usecase->type == PCM_PLAYBACK) {
821 usecase->devices = usecase->stream.out->devices;
822 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700823 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700824 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700826 if (usecase->stream.out == adev->primary_output &&
827 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800828 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
829 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700830 select_devices(adev, adev->active_input->usecase);
831 }
832 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 } else if (usecase->type == PCM_CAPTURE) {
834 usecase->devices = usecase->stream.in->device;
835 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700836 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700837 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530838 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
839 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
840 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
841 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700842 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800843 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700844 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
845 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700846 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700847 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700848 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 }
850 }
851
852 if (out_snd_device == usecase->out_snd_device &&
853 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800854 return 0;
855 }
856
sangwoobc677242013-08-08 16:53:43 +0900857 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700858 out_snd_device, platform_get_snd_device_name(out_snd_device),
859 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800861 /*
862 * Limitation: While in call, to do a device switch we need to disable
863 * and enable both RX and TX devices though one of them is same as current
864 * device.
865 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700866 if ((usecase->type == VOICE_CALL) &&
867 (usecase->in_snd_device != SND_DEVICE_NONE) &&
868 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800870 }
871
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 /* Disable current sound devices */
873 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700874 disable_audio_route(adev, usecase);
875 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 }
877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700879 disable_audio_route(adev, usecase);
880 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800881 }
882
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800883 /* Applicable only on the targets that has external modem.
884 * New device information should be sent to modem before enabling
885 * the devices to reduce in-call device switch time.
886 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700887 if ((usecase->type == VOICE_CALL) &&
888 (usecase->in_snd_device != SND_DEVICE_NONE) &&
889 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800890 status = platform_switch_voice_call_enable_device_config(adev->platform,
891 out_snd_device,
892 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700893 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895 /* Enable new sound devices */
896 if (out_snd_device != SND_DEVICE_NONE) {
897 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
898 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700899 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800900 }
901
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700902 if (in_snd_device != SND_DEVICE_NONE) {
903 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700904 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700905 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906
Avinash Vaish71a8b972014-07-24 15:36:33 +0530907 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700908 status = platform_switch_voice_call_device_post(adev->platform,
909 out_snd_device,
910 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530911 enable_audio_route_for_voice_usecases(adev, usecase);
912 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800913
sangwoo170731f2013-06-08 15:36:36 +0900914 usecase->in_snd_device = in_snd_device;
915 usecase->out_snd_device = out_snd_device;
916
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530917 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700918 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530919 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700920 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530921 usecase->stream.out->flags,
922 usecase->stream.out->format,
923 usecase->stream.out->sample_rate,
924 usecase->stream.out->bit_width,
925 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700926 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530927 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700928
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700929 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900930
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800931 /* Applicable only on the targets that has external modem.
932 * Enable device command should be sent to modem only after
933 * enabling voice call mixer controls
934 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700935 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800936 status = platform_switch_voice_call_usecase_route_post(adev->platform,
937 out_snd_device,
938 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530939 ALOGD("%s: done",__func__);
940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941 return status;
942}
943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944static int stop_input_stream(struct stream_in *in)
945{
946 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947 struct audio_usecase *uc_info;
948 struct audio_device *adev = in->dev;
949
Eric Laurentc8400632013-02-14 19:04:54 -0800950 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951
Eric Laurent994a6932013-07-17 11:51:42 -0700952 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954 uc_info = get_usecase_from_list(adev, in->usecase);
955 if (uc_info == NULL) {
956 ALOGE("%s: Could not find the usecase (%d) in the list",
957 __func__, in->usecase);
958 return -EINVAL;
959 }
960
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800961 /* Close in-call recording streams */
962 voice_check_and_stop_incall_rec_usecase(adev, in);
963
Eric Laurent150dbfe2013-02-27 14:31:02 -0800964 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700965 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966
967 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700968 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800969
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800970 list_remove(&uc_info->list);
971 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972
Eric Laurent994a6932013-07-17 11:51:42 -0700973 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974 return ret;
975}
976
977int start_input_stream(struct stream_in *in)
978{
979 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800980 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981 struct audio_usecase *uc_info;
982 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530983 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984
Mingming Yine62d7842013-10-25 16:26:03 -0700985 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530986 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
987 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700988
Naresh Tanniru80659832014-06-04 18:17:56 +0530989
990 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +0530991 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +0530992 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +0530993 goto error_config;
994 }
Naresh Tanniru4c630392014-05-12 01:05:52 +0530995
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700996 /* Check if source matches incall recording usecase criteria */
997 ret = voice_check_and_set_incall_rec_usecase(adev, in);
998 if (ret)
999 goto error_config;
1000 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001001 ALOGD("%s: Updated usecase(%d: %s)",
1002 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001003
Eric Laurentb23d5282013-05-14 15:27:20 -07001004 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005 if (in->pcm_device_id < 0) {
1006 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1007 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001008 ret = -EINVAL;
1009 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001011
1012 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001014
1015 if (!uc_info) {
1016 ret = -ENOMEM;
1017 goto error_config;
1018 }
1019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 uc_info->id = in->usecase;
1021 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001022 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001023 uc_info->devices = in->device;
1024 uc_info->in_snd_device = SND_DEVICE_NONE;
1025 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001026
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001027 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301028 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030
Eric Laurentc8400632013-02-14 19:04:54 -08001031 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001032 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1033
1034 unsigned int flags = PCM_IN;
1035 unsigned int pcm_open_retry_count = 0;
1036
1037 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1038 flags |= PCM_MMAP | PCM_NOIRQ;
1039 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1040 }
1041
1042 while (1) {
1043 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1044 flags, &in->config);
1045 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1046 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1047 if (in->pcm != NULL) {
1048 pcm_close(in->pcm);
1049 in->pcm = NULL;
1050 }
1051 if (pcm_open_retry_count-- == 0) {
1052 ret = -EIO;
1053 goto error_open;
1054 }
1055 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1056 continue;
1057 }
1058 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301060 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301061
Eric Laurent994a6932013-07-17 11:51:42 -07001062 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001063 return ret;
1064
1065error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301067 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001068
1069error_config:
1070 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001072
1073 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074}
1075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001076/* must be called with out->lock locked */
1077static int send_offload_cmd_l(struct stream_out* out, int command)
1078{
1079 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1080
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001081 if (!cmd) {
1082 ALOGE("failed to allocate mem for command 0x%x", command);
1083 return -ENOMEM;
1084 }
1085
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001086 ALOGVV("%s %d", __func__, command);
1087
1088 cmd->cmd = command;
1089 list_add_tail(&out->offload_cmd_list, &cmd->node);
1090 pthread_cond_signal(&out->offload_cond);
1091 return 0;
1092}
1093
1094/* must be called iwth out->lock locked */
1095static void stop_compressed_output_l(struct stream_out *out)
1096{
1097 out->offload_state = OFFLOAD_STATE_IDLE;
1098 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001099 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001100 if (out->compr != NULL) {
1101 compress_stop(out->compr);
1102 while (out->offload_thread_blocked) {
1103 pthread_cond_wait(&out->cond, &out->lock);
1104 }
1105 }
1106}
1107
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001108bool is_offload_usecase(audio_usecase_t uc_id)
1109{
1110 unsigned int i;
1111 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1112 if (uc_id == offload_usecases[i])
1113 return true;
1114 }
1115 return false;
1116}
1117
1118static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1119{
1120 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1121 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1122 char value[PROPERTY_VALUE_MAX] = {0};
1123
1124 property_get("audio.offload.multiple.enabled", value, NULL);
1125 if (!(atoi(value) || !strncmp("true", value, 4)))
1126 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1127
1128 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1129 for (i = 0; i < num_usecase; i++) {
1130 if (!(adev->offload_usecases_state & (0x1<<i))) {
1131 adev->offload_usecases_state |= 0x1 << i;
1132 ret = offload_usecases[i];
1133 break;
1134 }
1135 }
1136 ALOGV("%s: offload usecase is %d", __func__, ret);
1137 return ret;
1138}
1139
1140static void free_offload_usecase(struct audio_device *adev,
1141 audio_usecase_t uc_id)
1142{
1143 unsigned int i;
1144 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1145 if (offload_usecases[i] == uc_id) {
1146 adev->offload_usecases_state &= ~(0x1<<i);
1147 break;
1148 }
1149 }
1150 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1151}
1152
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001153static void *offload_thread_loop(void *context)
1154{
1155 struct stream_out *out = (struct stream_out *) context;
1156 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001157 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001159 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1160 set_sched_policy(0, SP_FOREGROUND);
1161 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1162
1163 ALOGV("%s", __func__);
1164 pthread_mutex_lock(&out->lock);
1165 for (;;) {
1166 struct offload_cmd *cmd = NULL;
1167 stream_callback_event_t event;
1168 bool send_callback = false;
1169
1170 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1171 __func__, list_empty(&out->offload_cmd_list),
1172 out->offload_state);
1173 if (list_empty(&out->offload_cmd_list)) {
1174 ALOGV("%s SLEEPING", __func__);
1175 pthread_cond_wait(&out->offload_cond, &out->lock);
1176 ALOGV("%s RUNNING", __func__);
1177 continue;
1178 }
1179
1180 item = list_head(&out->offload_cmd_list);
1181 cmd = node_to_item(item, struct offload_cmd, node);
1182 list_remove(item);
1183
1184 ALOGVV("%s STATE %d CMD %d out->compr %p",
1185 __func__, out->offload_state, cmd->cmd, out->compr);
1186
1187 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1188 free(cmd);
1189 break;
1190 }
1191
1192 if (out->compr == NULL) {
1193 ALOGE("%s: Compress handle is NULL", __func__);
1194 pthread_cond_signal(&out->cond);
1195 continue;
1196 }
1197 out->offload_thread_blocked = true;
1198 pthread_mutex_unlock(&out->lock);
1199 send_callback = false;
1200 switch(cmd->cmd) {
1201 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001202 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001204 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001205 send_callback = true;
1206 event = STREAM_CBK_EVENT_WRITE_READY;
1207 break;
1208 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001209 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301210 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001211 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301212 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001213 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301214 if (ret < 0)
1215 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301216 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301217 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001218 compress_drain(out->compr);
1219 else
1220 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301221 if (ret != -ENETRESET) {
1222 send_callback = true;
1223 event = STREAM_CBK_EVENT_DRAIN_READY;
1224 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1225 } else
1226 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001227 break;
1228 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001229 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001230 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001231 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001232 send_callback = true;
1233 event = STREAM_CBK_EVENT_DRAIN_READY;
1234 break;
1235 default:
1236 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1237 break;
1238 }
1239 pthread_mutex_lock(&out->lock);
1240 out->offload_thread_blocked = false;
1241 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001242 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001243 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001244 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001245 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001246 free(cmd);
1247 }
1248
1249 pthread_cond_signal(&out->cond);
1250 while (!list_empty(&out->offload_cmd_list)) {
1251 item = list_head(&out->offload_cmd_list);
1252 list_remove(item);
1253 free(node_to_item(item, struct offload_cmd, node));
1254 }
1255 pthread_mutex_unlock(&out->lock);
1256
1257 return NULL;
1258}
1259
1260static int create_offload_callback_thread(struct stream_out *out)
1261{
1262 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1263 list_init(&out->offload_cmd_list);
1264 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1265 offload_thread_loop, out);
1266 return 0;
1267}
1268
1269static int destroy_offload_callback_thread(struct stream_out *out)
1270{
1271 pthread_mutex_lock(&out->lock);
1272 stop_compressed_output_l(out);
1273 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1274
1275 pthread_mutex_unlock(&out->lock);
1276 pthread_join(out->offload_thread, (void **) NULL);
1277 pthread_cond_destroy(&out->offload_cond);
1278
1279 return 0;
1280}
1281
Eric Laurent07eeafd2013-10-06 12:52:49 -07001282static bool allow_hdmi_channel_config(struct audio_device *adev)
1283{
1284 struct listnode *node;
1285 struct audio_usecase *usecase;
1286 bool ret = true;
1287
1288 list_for_each(node, &adev->usecase_list) {
1289 usecase = node_to_item(node, struct audio_usecase, list);
1290 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1291 /*
1292 * If voice call is already existing, do not proceed further to avoid
1293 * disabling/enabling both RX and TX devices, CSD calls, etc.
1294 * Once the voice call done, the HDMI channels can be configured to
1295 * max channels of remaining use cases.
1296 */
1297 if (usecase->id == USECASE_VOICE_CALL) {
1298 ALOGD("%s: voice call is active, no change in HDMI channels",
1299 __func__);
1300 ret = false;
1301 break;
1302 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1303 ALOGD("%s: multi channel playback is active, "
1304 "no change in HDMI channels", __func__);
1305 ret = false;
1306 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001307 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001308 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001309 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1310 ", no change in HDMI channels", __func__,
1311 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001312 ret = false;
1313 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001314 }
1315 }
1316 }
1317 return ret;
1318}
1319
1320static int check_and_set_hdmi_channels(struct audio_device *adev,
1321 unsigned int channels)
1322{
1323 struct listnode *node;
1324 struct audio_usecase *usecase;
1325
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001326 unsigned int supported_channels = platform_edid_get_max_channels(
1327 adev->platform);
1328 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001329 /* Check if change in HDMI channel config is allowed */
1330 if (!allow_hdmi_channel_config(adev))
1331 return 0;
1332
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001333 if (channels > supported_channels)
1334 channels = supported_channels;
1335
Eric Laurent07eeafd2013-10-06 12:52:49 -07001336 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001337 ALOGD("%s: Requested channels are same as current channels(%d)",
1338 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001339 return 0;
1340 }
1341
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001342 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001343 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001344 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001345 adev->cur_hdmi_channels = channels;
1346
1347 /*
1348 * Deroute all the playback streams routed to HDMI so that
1349 * the back end is deactivated. Note that backend will not
1350 * be deactivated if any one stream is connected to it.
1351 */
1352 list_for_each(node, &adev->usecase_list) {
1353 usecase = node_to_item(node, struct audio_usecase, list);
1354 if (usecase->type == PCM_PLAYBACK &&
1355 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001356 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001357 }
1358 }
1359
1360 /*
1361 * Enable all the streams disabled above. Now the HDMI backend
1362 * will be activated with new channel configuration
1363 */
1364 list_for_each(node, &adev->usecase_list) {
1365 usecase = node_to_item(node, struct audio_usecase, list);
1366 if (usecase->type == PCM_PLAYBACK &&
1367 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001368 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001369 }
1370 }
1371
1372 return 0;
1373}
1374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375static int stop_output_stream(struct stream_out *out)
1376{
1377 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 struct audio_usecase *uc_info;
1379 struct audio_device *adev = out->dev;
1380
Eric Laurent994a6932013-07-17 11:51:42 -07001381 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001382 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383 uc_info = get_usecase_from_list(adev, out->usecase);
1384 if (uc_info == NULL) {
1385 ALOGE("%s: Could not find the usecase (%d) in the list",
1386 __func__, out->usecase);
1387 return -EINVAL;
1388 }
1389
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001390 if (is_offload_usecase(out->usecase) &&
1391 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001392 if (adev->visualizer_stop_output != NULL)
1393 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001394
1395 audio_extn_dts_remove_state_notifier_node(out->usecase);
1396
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001397 if (adev->offload_effects_stop_output != NULL)
1398 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1399 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001400
Eric Laurent150dbfe2013-02-27 14:31:02 -08001401 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001402 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403
1404 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001405 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001407 list_remove(&uc_info->list);
1408 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001410 if (is_offload_usecase(out->usecase) &&
1411 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1412 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1413 ALOGV("Disable passthrough , reset mixer to pcm");
1414 /* NO_PASSTHROUGH */
1415 out->compr_config.codec->compr_passthr = 0;
1416 audio_extn_dolby_set_hdmi_config(adev, out);
1417 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1418 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 /* Must be called after removing the usecase from list */
1420 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1421 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1422
Eric Laurent994a6932013-07-17 11:51:42 -07001423 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424 return ret;
1425}
1426
1427int start_output_stream(struct stream_out *out)
1428{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001430 int sink_channels = 0;
1431 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 struct audio_usecase *uc_info;
1433 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301434 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001436 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1437 ret = -EINVAL;
1438 goto error_config;
1439 }
1440
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301441 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1442 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1443 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301444
Naresh Tanniru80659832014-06-04 18:17:56 +05301445 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301446 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301447 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301448 goto error_config;
1449 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301450
Eric Laurentb23d5282013-05-14 15:27:20 -07001451 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 if (out->pcm_device_id < 0) {
1453 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1454 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001455 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001456 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 }
1458
1459 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001460
1461 if (!uc_info) {
1462 ret = -ENOMEM;
1463 goto error_config;
1464 }
1465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466 uc_info->id = out->usecase;
1467 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001468 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469 uc_info->devices = out->devices;
1470 uc_info->in_snd_device = SND_DEVICE_NONE;
1471 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001472 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001473 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001474 if (is_offload_usecase(out->usecase)) {
1475 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001476 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1477 }
1478 }
Mingming Yin9c041392014-05-01 15:37:31 -07001479 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1480 if (!strncmp("true", prop_value, 4)) {
1481 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001482 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1483 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001484 check_and_set_hdmi_channels(adev, sink_channels);
1485 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001486 if (is_offload_usecase(out->usecase)) {
1487 unsigned int ch_count = out->compr_config.codec->ch_in;
1488 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1489 /* backend channel config for passthrough stream is stereo */
1490 ch_count = 2;
1491 check_and_set_hdmi_channels(adev, ch_count);
1492 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001493 check_and_set_hdmi_channels(adev, out->config.channels);
1494 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001495 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001496 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001497 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 select_devices(adev, out->usecase);
1500
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001501 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1502 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001503 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001504 unsigned int flags = PCM_OUT;
1505 unsigned int pcm_open_retry_count = 0;
1506 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1507 flags |= PCM_MMAP | PCM_NOIRQ;
1508 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1509 } else
1510 flags |= PCM_MONOTONIC;
1511
1512 while (1) {
1513 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1514 flags, &out->config);
1515 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1516 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1517 if (out->pcm != NULL) {
1518 pcm_close(out->pcm);
1519 out->pcm = NULL;
1520 }
1521 if (pcm_open_retry_count-- == 0) {
1522 ret = -EIO;
1523 goto error_open;
1524 }
1525 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1526 continue;
1527 }
1528 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001529 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001530 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1531 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001532 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001533 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1534 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001536 out->compr = compress_open(adev->snd_card,
1537 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001538 COMPRESS_IN, &out->compr_config);
1539 if (out->compr && !is_compress_ready(out->compr)) {
1540 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1541 compress_close(out->compr);
1542 out->compr = NULL;
1543 ret = -EIO;
1544 goto error_open;
1545 }
1546 if (out->offload_callback)
1547 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001548
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001549 audio_extn_dts_create_state_notifier_node(out->usecase);
1550 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1551 popcount(out->channel_mask),
1552 out->playback_started);
1553
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001554#ifdef DS1_DOLBY_DDP_ENABLED
1555 if (audio_extn_is_dolby_format(out->format))
1556 audio_extn_dolby_send_ddp_endp_params(adev);
1557#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001558 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1559 if (adev->visualizer_start_output != NULL)
1560 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1561 if (adev->offload_effects_start_output != NULL)
1562 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001563 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 }
Eric Laurent994a6932013-07-17 11:51:42 -07001566 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001568error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001570error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001571 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572}
1573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574static int check_input_parameters(uint32_t sample_rate,
1575 audio_format_t format,
1576 int channel_count)
1577{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001578 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001580 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001581 !voice_extn_compress_voip_is_format_supported(format) &&
1582 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001583
1584 switch (channel_count) {
1585 case 1:
1586 case 2:
1587 case 6:
1588 break;
1589 default:
1590 ret = -EINVAL;
1591 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592
1593 switch (sample_rate) {
1594 case 8000:
1595 case 11025:
1596 case 12000:
1597 case 16000:
1598 case 22050:
1599 case 24000:
1600 case 32000:
1601 case 44100:
1602 case 48000:
1603 break;
1604 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001605 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 }
1607
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001608 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609}
1610
1611static size_t get_input_buffer_size(uint32_t sample_rate,
1612 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001613 int channel_count,
1614 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615{
1616 size_t size = 0;
1617
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001618 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1619 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001621 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001622 if (is_low_latency)
1623 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001624 /* ToDo: should use frame_size computed based on the format and
1625 channel_count here. */
1626 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001628 /* make sure the size is multiple of 32 bytes
1629 * At 48 kHz mono 16-bit PCM:
1630 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1631 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1632 */
1633 size += 0x1f;
1634 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001635
1636 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637}
1638
1639static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1640{
1641 struct stream_out *out = (struct stream_out *)stream;
1642
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001643 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644}
1645
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001646static int out_set_sample_rate(struct audio_stream *stream __unused,
1647 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648{
1649 return -ENOSYS;
1650}
1651
1652static size_t out_get_buffer_size(const struct audio_stream *stream)
1653{
1654 struct stream_out *out = (struct stream_out *)stream;
1655
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001656 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001658 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1659 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001661 return out->config.period_size *
1662 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663}
1664
1665static uint32_t out_get_channels(const struct audio_stream *stream)
1666{
1667 struct stream_out *out = (struct stream_out *)stream;
1668
1669 return out->channel_mask;
1670}
1671
1672static audio_format_t out_get_format(const struct audio_stream *stream)
1673{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001674 struct stream_out *out = (struct stream_out *)stream;
1675
1676 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677}
1678
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001679static int out_set_format(struct audio_stream *stream __unused,
1680 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681{
1682 return -ENOSYS;
1683}
1684
1685static int out_standby(struct audio_stream *stream)
1686{
1687 struct stream_out *out = (struct stream_out *)stream;
1688 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001689
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301690 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1691 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001692 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1693 /* Ignore standby in case of voip call because the voip output
1694 * stream is closed in adev_close_output_stream()
1695 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301696 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001697 return 0;
1698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001700 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001702 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001704 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001705 if (out->pcm) {
1706 pcm_close(out->pcm);
1707 out->pcm = NULL;
1708 }
1709 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001710 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001711 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001712 out->gapless_mdata.encoder_delay = 0;
1713 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 if (out->compr != NULL) {
1715 compress_close(out->compr);
1716 out->compr = NULL;
1717 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001718 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001720 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721 }
1722 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001723 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724 return 0;
1725}
1726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001727static int out_dump(const struct audio_stream *stream __unused,
1728 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729{
1730 return 0;
1731}
1732
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001733static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1734{
1735 int ret = 0;
1736 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001737 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001738 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001739 tmp_mdata.encoder_delay = 0;
1740 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001741 tmp_mdata.min_blk_size = 0;
1742 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001743
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001744 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001745 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001746 return -EINVAL;
1747 }
1748
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001749 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1750 if (ret >= 0) {
1751 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1752 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1753 ALOGV("ADTS format is set in offload mode");
1754 }
1755 out->send_new_metadata = 1;
1756 }
1757
Mingming Yin3ee55c62014-08-04 14:23:35 -07001758 if (out->format == AUDIO_FORMAT_FLAC) {
1759 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1760 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001761 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001762 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1763 out->send_new_metadata = 1;
1764 }
1765 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1766 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001767 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001768 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1769 out->send_new_metadata = 1;
1770 }
1771 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1772 if (ret >= 0) {
1773 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1774 out->send_new_metadata = 1;
1775 }
1776 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1777 if (ret >= 0) {
1778 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1779 out->send_new_metadata = 1;
1780 }
1781 }
1782
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001783 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1784 if(ret >= 0)
1785 is_meta_data_params = true;
1786 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1787 if(ret >= 0 )
1788 is_meta_data_params = true;
1789 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1790 if(ret >= 0 )
1791 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001792 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1793 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001794 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001795 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001796 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001797 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1798 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001799 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001800 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001801 }
1802
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001803 if(!is_meta_data_params) {
1804 ALOGV("%s: Not gapless meta data params", __func__);
1805 return 0;
1806 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001807 out->gapless_mdata = tmp_mdata;
1808 out->send_new_metadata = 1;
1809 ALOGV("%s new encoder delay %u and padding %u", __func__,
1810 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1811
1812 return 0;
1813}
1814
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001815static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1816{
1817 return out == adev->primary_output || out == adev->voice_tx_output;
1818}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1821{
1822 struct stream_out *out = (struct stream_out *)stream;
1823 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001824 struct audio_usecase *usecase;
1825 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 struct str_parms *parms;
1827 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001828 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001829 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
sangwoobc677242013-08-08 16:53:43 +09001831 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001832 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301834 if (!parms)
1835 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001836 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1837 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001840 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001842 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301843 * When HDMI cable is unplugged/usb hs is disconnected the
1844 * music playback is paused and the policy manager sends routing=0
1845 * But the audioflingercontinues to write data until standby time
1846 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001847 * Avoid this by routing audio to speaker until standby.
1848 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301849 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1850 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001852 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1853 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001854 }
1855
1856 /*
1857 * select_devices() call below switches all the usecases on the same
1858 * backend to the new device. Refer to check_usecases_codec_backend() in
1859 * the select_devices(). But how do we undo this?
1860 *
1861 * For example, music playback is active on headset (deep-buffer usecase)
1862 * and if we go to ringtones and select a ringtone, low-latency usecase
1863 * will be started on headset+speaker. As we can't enable headset+speaker
1864 * and headset devices at the same time, select_devices() switches the music
1865 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1866 * So when the ringtone playback is completed, how do we undo the same?
1867 *
1868 * We are relying on the out_set_parameters() call on deep-buffer output,
1869 * once the ringtone playback is ended.
1870 * NOTE: We should not check if the current devices are same as new devices.
1871 * Because select_devices() must be called to switch back the music
1872 * playback to headset.
1873 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001874 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875 out->devices = val;
1876
1877 if (!out->standby)
1878 select_devices(adev, out->usecase);
1879
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001880 if (output_drives_call(adev, out)) {
1881 if(!voice_is_in_call(adev)) {
1882 if (adev->mode == AUDIO_MODE_IN_CALL) {
1883 adev->current_call_output = out;
1884 ret = voice_start_call(adev);
1885 }
1886 } else {
1887 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001888 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001889 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001890 }
1891 }
1892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001894 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001896
1897 if (out == adev->primary_output) {
1898 pthread_mutex_lock(&adev->lock);
1899 audio_extn_set_parameters(adev, parms);
1900 pthread_mutex_unlock(&adev->lock);
1901 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001902 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001903 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001904 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001905
1906 audio_extn_dts_create_state_notifier_node(out->usecase);
1907 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1908 popcount(out->channel_mask),
1909 out->playback_started);
1910
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001911 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001912 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301915error:
Eric Laurent994a6932013-07-17 11:51:42 -07001916 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917 return ret;
1918}
1919
1920static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1921{
1922 struct stream_out *out = (struct stream_out *)stream;
1923 struct str_parms *query = str_parms_create_str(keys);
1924 char *str;
1925 char value[256];
1926 struct str_parms *reply = str_parms_create();
1927 size_t i, j;
1928 int ret;
1929 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001930
1931 if (!query || !reply) {
1932 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1933 return NULL;
1934 }
1935
Eric Laurent994a6932013-07-17 11:51:42 -07001936 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1938 if (ret >= 0) {
1939 value[0] = '\0';
1940 i = 0;
1941 while (out->supported_channel_masks[i] != 0) {
1942 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1943 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1944 if (!first) {
1945 strcat(value, "|");
1946 }
1947 strcat(value, out_channels_name_to_enum_table[j].name);
1948 first = false;
1949 break;
1950 }
1951 }
1952 i++;
1953 }
1954 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1955 str = str_parms_to_str(reply);
1956 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001957 voice_extn_out_get_parameters(out, query, reply);
1958 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001959 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001960 free(str);
1961 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001962 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001964
1965 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1966 if (ret >= 0) {
1967 value[0] = '\0';
1968 i = 0;
1969 first = true;
1970 while (out->supported_formats[i] != 0) {
1971 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1972 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1973 if (!first) {
1974 strcat(value, "|");
1975 }
1976 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1977 first = false;
1978 break;
1979 }
1980 }
1981 i++;
1982 }
1983 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
1984 str = str_parms_to_str(reply);
1985 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 str_parms_destroy(query);
1987 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 return str;
1990}
1991
1992static uint32_t out_get_latency(const struct audio_stream_out *stream)
1993{
1994 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08001995 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996
Alexy Josephaa54c872014-12-03 02:46:47 -08001997 if (is_offload_usecase(out->usecase)) {
1998 if (out->use_small_bufs == true)
1999 latency = ((out->compr_config.fragments *
2000 out->compr_config.fragment_size * 1000) /
2001 (out->sample_rate * out->compr_config.codec->ch_in *
2002 audio_bytes_per_sample(out->format)));
2003 else
2004 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2005 } else {
2006 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002008 }
2009
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302010 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002011 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012}
2013
2014static int out_set_volume(struct audio_stream_out *stream, float left,
2015 float right)
2016{
Eric Laurenta9024de2013-04-04 09:19:12 -07002017 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002018 int volume[2];
2019
Eric Laurenta9024de2013-04-04 09:19:12 -07002020 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2021 /* only take left channel into account: the API is for stereo anyway */
2022 out->muted = (left == 0.0f);
2023 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002024 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002025 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2026 /*
2027 * Set mute or umute on HDMI passthrough stream.
2028 * Only take left channel into account.
2029 * Mute is 0 and unmute 1
2030 */
2031 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2032 } else {
2033 char mixer_ctl_name[128];
2034 struct audio_device *adev = out->dev;
2035 struct mixer_ctl *ctl;
2036 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002037 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002039 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2040 "Compress Playback %d Volume", pcm_device_id);
2041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2042 if (!ctl) {
2043 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2044 __func__, mixer_ctl_name);
2045 return -EINVAL;
2046 }
2047 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2048 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2049 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2050 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 return -ENOSYS;
2055}
2056
2057static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2058 size_t bytes)
2059{
2060 struct stream_out *out = (struct stream_out *)stream;
2061 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302062 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002063 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302066
Naresh Tanniru80659832014-06-04 18:17:56 +05302067 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2068 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302069 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302070 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302071 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002072 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302073 //during SSR for compress usecase we should return error to flinger
2074 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2075 pthread_mutex_unlock(&out->lock);
2076 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302077 }
2078 }
2079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002081 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002082 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002083 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2084 ret = voice_extn_compress_voip_start_output_stream(out);
2085 else
2086 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002087 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002088 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002090 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 goto exit;
2092 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002095 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002096 ALOGD("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002097 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002098 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002099 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2100 out->send_new_metadata = 0;
2101 }
2102
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302104 if (ret < 0)
2105 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002106 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002107 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302108 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302110 } else if (-ENETRESET == ret) {
2111 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2112 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2113 pthread_mutex_unlock(&out->lock);
2114 out_standby(&out->stream.common);
2115 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302117 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 compress_start(out->compr);
2119 out->playback_started = 1;
2120 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002121
2122 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2123 popcount(out->channel_mask),
2124 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 }
2126 pthread_mutex_unlock(&out->lock);
2127 return ret;
2128 } else {
2129 if (out->pcm) {
2130 if (out->muted)
2131 memset((void *)buffer, 0, bytes);
2132 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002133 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2134 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2135 else
2136 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302137 if (ret < 0)
2138 ret = -errno;
2139 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002140 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 }
2143
2144exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302145 /* ToDo: There may be a corner case when SSR happens back to back during
2146 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302147 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302148 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302149 }
2150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 pthread_mutex_unlock(&out->lock);
2152
2153 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002154 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002155 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302156 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302157 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302158 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302159 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302160 out->standby = true;
2161 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002163 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302164 out_get_sample_rate(&out->stream.common));
2165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 }
2167 return bytes;
2168}
2169
2170static int out_get_render_position(const struct audio_stream_out *stream,
2171 uint32_t *dsp_frames)
2172{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302174 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002175 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002176 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002177 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 pthread_mutex_lock(&out->lock);
2179 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302180 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302182 if (ret < 0)
2183 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002184 ALOGVV("%s rendered frames %d sample_rate %d",
2185 __func__, *dsp_frames, out->sample_rate);
2186 }
2187 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302188 if (-ENETRESET == ret) {
2189 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2190 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2191 return -EINVAL;
2192 } else if(ret < 0) {
2193 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2194 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302195 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2196 /*
2197 * Handle corner case where compress session is closed during SSR
2198 * and timestamp is queried
2199 */
2200 ALOGE(" ERROR: sound card not active, return error");
2201 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302202 } else {
2203 return 0;
2204 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 } else
2206 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207}
2208
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002209static int out_add_audio_effect(const struct audio_stream *stream __unused,
2210 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211{
2212 return 0;
2213}
2214
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002215static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2216 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217{
2218 return 0;
2219}
2220
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002221static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2222 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223{
2224 return -EINVAL;
2225}
2226
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002227static int out_get_presentation_position(const struct audio_stream_out *stream,
2228 uint64_t *frames, struct timespec *timestamp)
2229{
2230 struct stream_out *out = (struct stream_out *)stream;
2231 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002232 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002233
2234 pthread_mutex_lock(&out->lock);
2235
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002236 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002237 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302238 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002239 &out->sample_rate);
2240 ALOGVV("%s rendered frames %ld sample_rate %d",
2241 __func__, dsp_frames, out->sample_rate);
2242 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302243 if (ret < 0)
2244 ret = -errno;
2245 if (-ENETRESET == ret) {
2246 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2247 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2248 ret = -EINVAL;
2249 } else
2250 ret = 0;
2251
Eric Laurent949a0892013-09-20 09:20:13 -07002252 /* this is the best we can do */
2253 clock_gettime(CLOCK_MONOTONIC, timestamp);
2254 }
2255 } else {
2256 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002257 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002258 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2259 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002260 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002261 // This adjustment accounts for buffering after app processor.
2262 // It is based on estimated DSP latency per use case, rather than exact.
2263 signed_frames -=
2264 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2265
Eric Laurent949a0892013-09-20 09:20:13 -07002266 // It would be unusual for this value to be negative, but check just in case ...
2267 if (signed_frames >= 0) {
2268 *frames = signed_frames;
2269 ret = 0;
2270 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002271 }
2272 }
2273 }
2274
2275 pthread_mutex_unlock(&out->lock);
2276
2277 return ret;
2278}
2279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002280static int out_set_callback(struct audio_stream_out *stream,
2281 stream_callback_t callback, void *cookie)
2282{
2283 struct stream_out *out = (struct stream_out *)stream;
2284
2285 ALOGV("%s", __func__);
2286 pthread_mutex_lock(&out->lock);
2287 out->offload_callback = callback;
2288 out->offload_cookie = cookie;
2289 pthread_mutex_unlock(&out->lock);
2290 return 0;
2291}
2292
2293static int out_pause(struct audio_stream_out* stream)
2294{
2295 struct stream_out *out = (struct stream_out *)stream;
2296 int status = -ENOSYS;
2297 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002298 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002299 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002300 pthread_mutex_lock(&out->lock);
2301 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302302 struct audio_device *adev = out->dev;
2303 int snd_scard_state = get_snd_card_state(adev);
2304
2305 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2306 status = compress_pause(out->compr);
2307
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002308 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002309
2310 audio_extn_dts_eagle_fade(adev, false);
2311 audio_extn_dts_notify_playback_state(out->usecase, 0,
2312 out->sample_rate, popcount(out->channel_mask),
2313 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002314 }
2315 pthread_mutex_unlock(&out->lock);
2316 }
2317 return status;
2318}
2319
2320static int out_resume(struct audio_stream_out* stream)
2321{
2322 struct stream_out *out = (struct stream_out *)stream;
2323 int status = -ENOSYS;
2324 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002325 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002326 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327 status = 0;
2328 pthread_mutex_lock(&out->lock);
2329 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302330 struct audio_device *adev = out->dev;
2331 int snd_scard_state = get_snd_card_state(adev);
2332
2333 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2334 status = compress_resume(out->compr);
2335
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002337
2338 audio_extn_dts_eagle_fade(adev, true);
2339 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2340 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 }
2342 pthread_mutex_unlock(&out->lock);
2343 }
2344 return status;
2345}
2346
2347static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350 int status = -ENOSYS;
2351 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002352 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 pthread_mutex_lock(&out->lock);
2354 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2355 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2356 else
2357 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2358 pthread_mutex_unlock(&out->lock);
2359 }
2360 return status;
2361}
2362
2363static int out_flush(struct audio_stream_out* stream)
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002367 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002368 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 pthread_mutex_lock(&out->lock);
2370 stop_compressed_output_l(out);
2371 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002372 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 return 0;
2374 }
2375 return -ENOSYS;
2376}
2377
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378/** audio_stream_in implementation **/
2379static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2380{
2381 struct stream_in *in = (struct stream_in *)stream;
2382
2383 return in->config.rate;
2384}
2385
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002386static int in_set_sample_rate(struct audio_stream *stream __unused,
2387 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388{
2389 return -ENOSYS;
2390}
2391
2392static size_t in_get_buffer_size(const struct audio_stream *stream)
2393{
2394 struct stream_in *in = (struct stream_in *)stream;
2395
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002396 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2397 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002398 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2399 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002400
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002401 return in->config.period_size *
2402 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403}
2404
2405static uint32_t in_get_channels(const struct audio_stream *stream)
2406{
2407 struct stream_in *in = (struct stream_in *)stream;
2408
2409 return in->channel_mask;
2410}
2411
2412static audio_format_t in_get_format(const struct audio_stream *stream)
2413{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002414 struct stream_in *in = (struct stream_in *)stream;
2415
2416 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417}
2418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002419static int in_set_format(struct audio_stream *stream __unused,
2420 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421{
2422 return -ENOSYS;
2423}
2424
2425static int in_standby(struct audio_stream *stream)
2426{
2427 struct stream_in *in = (struct stream_in *)stream;
2428 struct audio_device *adev = in->dev;
2429 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302430 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2431 stream, in->usecase, use_case_table[in->usecase]);
2432
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002433 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2434 /* Ignore standby in case of voip call because the voip input
2435 * stream is closed in adev_close_input_stream()
2436 */
2437 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2438 return status;
2439 }
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002442 if (!in->standby && in->is_st_session) {
2443 ALOGD("%s: sound trigger pcm stop lab", __func__);
2444 audio_extn_sound_trigger_stop_lab(in);
2445 in->standby = 1;
2446 }
2447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002449 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002451 if (in->pcm) {
2452 pcm_close(in->pcm);
2453 in->pcm = NULL;
2454 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002456 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 }
2458 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002459 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return status;
2461}
2462
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002463static int in_dump(const struct audio_stream *stream __unused,
2464 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465{
2466 return 0;
2467}
2468
2469static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2470{
2471 struct stream_in *in = (struct stream_in *)stream;
2472 struct audio_device *adev = in->dev;
2473 struct str_parms *parms;
2474 char *str;
2475 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002476 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302478 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 parms = str_parms_create_str(kvpairs);
2480
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302481 if (!parms)
2482 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002484 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002485
2486 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2487 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 val = atoi(value);
2489 /* no audio source uses val == 0 */
2490 if ((in->source != val) && (val != 0)) {
2491 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002492 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2493 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2494 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2495 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002496 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002497 err = voice_extn_compress_voip_open_input_stream(in);
2498 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002499 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002500 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002501 }
2502 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 }
2504 }
2505
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002506 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2507 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002509 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 in->device = val;
2511 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002512 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002513 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 }
2515 }
2516
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002517done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520
2521 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302522error:
Eric Laurent994a6932013-07-17 11:51:42 -07002523 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 return ret;
2525}
2526
2527static char* in_get_parameters(const struct audio_stream *stream,
2528 const char *keys)
2529{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002530 struct stream_in *in = (struct stream_in *)stream;
2531 struct str_parms *query = str_parms_create_str(keys);
2532 char *str;
2533 char value[256];
2534 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002535
2536 if (!query || !reply) {
2537 ALOGE("in_get_parameters: failed to create query or reply");
2538 return NULL;
2539 }
2540
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002541 ALOGV("%s: enter: keys - %s", __func__, keys);
2542
2543 voice_extn_in_get_parameters(in, query, reply);
2544
2545 str = str_parms_to_str(reply);
2546 str_parms_destroy(query);
2547 str_parms_destroy(reply);
2548
2549 ALOGV("%s: exit: returns - %s", __func__, str);
2550 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551}
2552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002553static int in_set_gain(struct audio_stream_in *stream __unused,
2554 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555{
2556 return 0;
2557}
2558
2559static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2560 size_t bytes)
2561{
2562 struct stream_in *in = (struct stream_in *)stream;
2563 struct audio_device *adev = in->dev;
2564 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302565 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302568
2569 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302570 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302571 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302572 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302573 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002574 } else {
2575 if (in->is_st_session && !in->is_st_session_active) {
2576 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2577 ret= -EIO;;
2578 goto exit;
2579 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302580 }
2581 }
2582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002584 if (!in->is_st_session) {
2585 pthread_mutex_lock(&adev->lock);
2586 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2587 ret = voice_extn_compress_voip_start_input_stream(in);
2588 else
2589 ret = start_input_stream(in);
2590 pthread_mutex_unlock(&adev->lock);
2591 if (ret != 0) {
2592 goto exit;
2593 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 }
2595 in->standby = 0;
2596 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597
2598 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002599 if (audio_extn_ssr_get_enabled() &&
2600 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002601 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002602 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2603 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002604 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2605 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002606 else
2607 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302608 if (ret < 0)
2609 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 }
2611
2612 /*
2613 * Instead of writing zeroes here, we could trust the hardware
2614 * to always provide zeroes when muted.
2615 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302616 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2617 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 memset(buffer, 0, bytes);
2619
2620exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302621 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302622 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302623 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002624 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2625 session reading on LAB data. In this case do not set sound card state
2626 offline, instead mark this sound trigger session inactive to avoid
2627 further reading of LAB data from CPE driver. Marking the session
2628 inactive handles both CPE and ADSP SSR for sound trigger session */
2629 if (!in->is_st_session)
2630 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2631 else
2632 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 pthread_mutex_unlock(&in->lock);
2635
2636 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302637 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302638 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302639 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302640 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302641 in->standby = true;
2642 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302643 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002645 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002646 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302647 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 }
2649 return bytes;
2650}
2651
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002652static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002653{
2654 return 0;
2655}
2656
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002657static int add_remove_audio_effect(const struct audio_stream *stream,
2658 effect_handle_t effect,
2659 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002661 struct stream_in *in = (struct stream_in *)stream;
2662 int status = 0;
2663 effect_descriptor_t desc;
2664
2665 status = (*effect)->get_descriptor(effect, &desc);
2666 if (status != 0)
2667 return status;
2668
2669 pthread_mutex_lock(&in->lock);
2670 pthread_mutex_lock(&in->dev->lock);
2671 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2672 in->enable_aec != enable &&
2673 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2674 in->enable_aec = enable;
2675 if (!in->standby)
2676 select_devices(in->dev, in->usecase);
2677 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002678 if (in->enable_ns != enable &&
2679 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2680 in->enable_ns = enable;
2681 if (!in->standby)
2682 select_devices(in->dev, in->usecase);
2683 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002684 pthread_mutex_unlock(&in->dev->lock);
2685 pthread_mutex_unlock(&in->lock);
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 return 0;
2688}
2689
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002690static int in_add_audio_effect(const struct audio_stream *stream,
2691 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692{
Eric Laurent994a6932013-07-17 11:51:42 -07002693 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002694 return add_remove_audio_effect(stream, effect, true);
2695}
2696
2697static int in_remove_audio_effect(const struct audio_stream *stream,
2698 effect_handle_t effect)
2699{
Eric Laurent994a6932013-07-17 11:51:42 -07002700 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002701 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702}
2703
2704static int adev_open_output_stream(struct audio_hw_device *dev,
2705 audio_io_handle_t handle,
2706 audio_devices_t devices,
2707 audio_output_flags_t flags,
2708 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002709 struct audio_stream_out **stream_out,
2710 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711{
2712 struct audio_device *adev = (struct audio_device *)dev;
2713 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002714 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002715 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302718
2719 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2720 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2721 ALOGE(" sound card is not active rejecting compress output open request");
2722 return -EINVAL;
2723 }
2724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2726
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302727 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2728 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2729 devices, flags, &out->stream);
2730
2731
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002732 if (!out) {
2733 return -ENOMEM;
2734 }
2735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 if (devices == AUDIO_DEVICE_NONE)
2737 devices = AUDIO_DEVICE_OUT_SPEAKER;
2738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 out->flags = flags;
2740 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002741 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002742 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002743 out->sample_rate = config->sample_rate;
2744 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2745 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002746 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002747 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002748 out->non_blocking = 0;
2749 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750
2751 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002752 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2753 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2754 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2755
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002756 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002757 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2758 ret = read_hdmi_channel_masks(out);
2759
2760 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2761 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002762 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002763 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002764 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002765
2766 if (config->sample_rate == 0)
2767 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2768 if (config->channel_mask == 0)
2769 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2770
2771 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002772 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2774 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002776 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002778 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2779 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002780 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002781 ret = voice_extn_compress_voip_open_output_stream(out);
2782 if (ret != 0) {
2783 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2784 __func__, ret);
2785 goto error_open;
2786 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002787 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2788 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2789 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2790 ALOGE("%s: Unsupported Offload information", __func__);
2791 ret = -EINVAL;
2792 goto error_open;
2793 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002794
2795 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2796 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2797 ALOGV("read and update_pass through formats");
2798 ret = audio_extn_dolby_update_passt_formats(adev, out);
2799 if(ret != 0) {
2800 goto error_open;
2801 }
2802 if(config->offload_info.format == 0)
2803 config->offload_info.format = out->supported_formats[0];
2804 }
2805
Mingming Yin90310102013-11-13 16:57:00 -08002806 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002807 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808 ALOGE("%s: Unsupported audio format", __func__);
2809 ret = -EINVAL;
2810 goto error_open;
2811 }
2812
2813 out->compr_config.codec = (struct snd_codec *)
2814 calloc(1, sizeof(struct snd_codec));
2815
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002816 if (!out->compr_config.codec) {
2817 ret = -ENOMEM;
2818 goto error_open;
2819 }
2820
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002821 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 if (config->offload_info.channel_mask)
2823 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002824 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002826 config->offload_info.channel_mask = config->channel_mask;
2827 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002828 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829 out->sample_rate = config->offload_info.sample_rate;
2830
2831 out->stream.set_callback = out_set_callback;
2832 out->stream.pause = out_pause;
2833 out->stream.resume = out_resume;
2834 out->stream.drain = out_drain;
2835 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002836 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002838 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002839 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002840 audio_extn_dolby_get_snd_codec_id(adev, out,
2841 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002842 else
2843 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002845 if (audio_is_offload_pcm(config->offload_info.format)) {
2846 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002847 platform_get_pcm_offload_buffer_size(&config->offload_info);
2848 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2849 out->compr_config.fragment_size =
2850 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002851 } else {
2852 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002853 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002854 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2856 out->compr_config.codec->sample_rate =
2857 compress_get_alsa_rate(config->offload_info.sample_rate);
2858 out->compr_config.codec->bit_rate =
2859 config->offload_info.bit_rate;
2860 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002861 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002863 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002864 /*TODO: Do we need to change it for passthrough */
2865 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866
Mingming Yin3ee55c62014-08-04 14:23:35 -07002867 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2868 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002869 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2870 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002871 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002872 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2873
Mingming Yin3ee55c62014-08-04 14:23:35 -07002874 if (out->bit_width == 24) {
2875 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2876 }
2877
Amit Shekhar6f461b12014-08-01 14:52:58 -07002878 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002879 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002880
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2882 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002883
Alexy Josephaa54c872014-12-03 02:46:47 -08002884 if (config->offload_info.use_small_bufs) {
2885 //this flag is set from framework only if its for PCM formats
2886 //no need to check for PCM format again
2887 out->non_blocking = 0;
2888 out->use_small_bufs = true;
2889 ALOGI("Keep write blocking for small buff: non_blockling %d",
2890 out->non_blocking);
2891 }
2892
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002893 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002894 out->offload_state = OFFLOAD_STATE_IDLE;
2895 out->playback_started = 0;
2896
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002897 audio_extn_dts_create_state_notifier_node(out->usecase);
2898
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 create_offload_callback_thread(out);
2900 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2901 __func__, config->offload_info.version,
2902 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002903 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002904 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002905 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2906 ret = voice_check_and_set_incall_music_usecase(adev, out);
2907 if (ret != 0) {
2908 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2909 __func__, ret);
2910 goto error_open;
2911 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002912 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2913 if (config->sample_rate == 0)
2914 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2915 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2916 config->sample_rate != 8000) {
2917 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2918 ret = -EINVAL;
2919 goto error_open;
2920 }
2921 out->sample_rate = config->sample_rate;
2922 out->config.rate = config->sample_rate;
2923 if (config->format == AUDIO_FORMAT_DEFAULT)
2924 config->format = AUDIO_FORMAT_PCM_16_BIT;
2925 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2926 config->format = AUDIO_FORMAT_PCM_16_BIT;
2927 ret = -EINVAL;
2928 goto error_open;
2929 }
2930 out->format = config->format;
2931 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2932 out->config = pcm_config_afe_proxy_playback;
2933 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002934 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002935 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2937 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002938 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002939 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002940 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002941 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002942 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002943 out->config = pcm_config_deep_buffer;
2944 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 }
2946
Amit Shekhar1d896042014-10-03 13:16:09 -07002947 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2948 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002949 /* TODO remove this hardcoding and check why width is zero*/
2950 if (out->bit_width == 0)
2951 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002952 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2953 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002954 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002955 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002956 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2957 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2958 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002959 if(adev->primary_output == NULL)
2960 adev->primary_output = out;
2961 else {
2962 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002963 ret = -EEXIST;
2964 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002965 }
2966 }
2967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 /* Check if this usecase is already existing */
2969 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002970 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2971 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002974 ret = -EEXIST;
2975 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 }
2977 pthread_mutex_unlock(&adev->lock);
2978
2979 out->stream.common.get_sample_rate = out_get_sample_rate;
2980 out->stream.common.set_sample_rate = out_set_sample_rate;
2981 out->stream.common.get_buffer_size = out_get_buffer_size;
2982 out->stream.common.get_channels = out_get_channels;
2983 out->stream.common.get_format = out_get_format;
2984 out->stream.common.set_format = out_set_format;
2985 out->stream.common.standby = out_standby;
2986 out->stream.common.dump = out_dump;
2987 out->stream.common.set_parameters = out_set_parameters;
2988 out->stream.common.get_parameters = out_get_parameters;
2989 out->stream.common.add_audio_effect = out_add_audio_effect;
2990 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2991 out->stream.get_latency = out_get_latency;
2992 out->stream.set_volume = out_set_volume;
2993 out->stream.write = out_write;
2994 out->stream.get_render_position = out_get_render_position;
2995 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002996 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002999 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003000 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003002 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3003 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 config->format = out->stream.common.get_format(&out->stream.common);
3006 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3007 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3008
3009 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303010 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3011 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003012
3013 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3014 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3015 popcount(out->channel_mask), out->playback_started);
3016
Eric Laurent994a6932013-07-17 11:51:42 -07003017 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003019
3020error_open:
3021 free(out);
3022 *stream_out = NULL;
3023 ALOGD("%s: exit: ret %d", __func__, ret);
3024 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025}
3026
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003027static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 struct audio_stream_out *stream)
3029{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 struct stream_out *out = (struct stream_out *)stream;
3031 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003032 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303034 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3035
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003036 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303037 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003038 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303039 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003040 if(ret != 0)
3041 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3042 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003043 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003044 out_standby(&stream->common);
3045
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003046 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003047 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003049 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 if (out->compr_config.codec != NULL)
3051 free(out->compr_config.codec);
3052 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003053
3054 if (adev->voice_tx_output == out)
3055 adev->voice_tx_output = NULL;
3056
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 pthread_cond_destroy(&out->cond);
3058 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003060 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061}
3062
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003063static void close_compress_sessions(struct audio_device *adev)
3064{
Mingming Yin7b762e72015-03-04 13:47:32 -08003065 struct stream_out *out;
3066 struct listnode *node;
3067 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003068 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003069 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003070 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003071 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003072 if (usecase && usecase->stream.out) {
3073 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3074 out = usecase->stream.out;
3075 pthread_mutex_unlock(&adev->lock);
3076 out_standby(&out->stream.common);
3077 pthread_mutex_lock(&adev->lock);
3078 }
3079 }
3080 }
3081 pthread_mutex_unlock(&adev->lock);
3082}
3083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3085{
3086 struct audio_device *adev = (struct audio_device *)dev;
3087 struct str_parms *parms;
3088 char *str;
3089 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003090 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003091 int ret;
3092 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003094 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303097 if (!parms)
3098 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003099 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3100 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303101 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303102 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303103 struct listnode *node;
3104 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303105 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303106 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003107 //close compress sessions on OFFLINE status
3108 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303109 } else if (strstr(snd_card_status, "ONLINE")) {
3110 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303111 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303112 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303113 }
3114
3115 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003116 status = voice_set_parameters(adev, parms);
3117 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003118 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003120 status = platform_set_parameters(adev->platform, parms);
3121 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003122 goto done;
3123
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003124 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3125 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003126 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3128 adev->bluetooth_nrec = true;
3129 else
3130 adev->bluetooth_nrec = false;
3131 }
3132
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003133 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3134 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3136 adev->screen_off = false;
3137 else
3138 adev->screen_off = true;
3139 }
3140
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003141 ret = str_parms_get_int(parms, "rotation", &val);
3142 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003143 bool reverse_speakers = false;
3144 switch(val) {
3145 // FIXME: note that the code below assumes that the speakers are in the correct placement
3146 // relative to the user when the device is rotated 90deg from its default rotation. This
3147 // assumption is device-specific, not platform-specific like this code.
3148 case 270:
3149 reverse_speakers = true;
3150 break;
3151 case 0:
3152 case 90:
3153 case 180:
3154 break;
3155 default:
3156 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003157 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003158 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003159 if (status == 0) {
3160 if (adev->speaker_lr_swap != reverse_speakers) {
3161 adev->speaker_lr_swap = reverse_speakers;
3162 // only update the selected device if there is active pcm playback
3163 struct audio_usecase *usecase;
3164 struct listnode *node;
3165 list_for_each(node, &adev->usecase_list) {
3166 usecase = node_to_item(node, struct audio_usecase, list);
3167 if (usecase->type == PCM_PLAYBACK) {
3168 select_devices(adev, usecase->id);
3169 break;
3170 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003171 }
3172 }
3173 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003174 }
3175
Mingming Yin514a8bc2014-07-29 15:22:21 -07003176 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3177 if (ret >= 0) {
3178 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3179 adev->bt_wb_speech_enabled = true;
3180 else
3181 adev->bt_wb_speech_enabled = false;
3182 }
3183
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003184 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3185 if (ret >= 0) {
3186 val = atoi(value);
3187 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3188 ALOGV("cache new edid");
3189 platform_cache_edid(adev->platform);
3190 }
3191 }
3192
3193 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3194 if (ret >= 0) {
3195 val = atoi(value);
3196 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3197 ALOGV("invalidate cached edid");
3198 platform_invalidate_edid(adev->platform);
3199 }
3200 }
3201
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003202 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003203
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003204done:
3205 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003206 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303207error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003208 ALOGV("%s: exit with code(%d)", __func__, status);
3209 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210}
3211
3212static char* adev_get_parameters(const struct audio_hw_device *dev,
3213 const char *keys)
3214{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003215 struct audio_device *adev = (struct audio_device *)dev;
3216 struct str_parms *reply = str_parms_create();
3217 struct str_parms *query = str_parms_create_str(keys);
3218 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303219 char value[256] = {0};
3220 int ret = 0;
3221
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003222 if (!query || !reply) {
3223 ALOGE("adev_get_parameters: failed to create query or reply");
3224 return NULL;
3225 }
3226
Naresh Tannirud7205b62014-06-20 02:54:48 +05303227 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3228 sizeof(value));
3229 if (ret >=0) {
3230 int val = 1;
3231 pthread_mutex_lock(&adev->snd_card_status.lock);
3232 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3233 val = 0;
3234 pthread_mutex_unlock(&adev->snd_card_status.lock);
3235 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3236 goto exit;
3237 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003238
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003239 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003240 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003241 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003242 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303243 pthread_mutex_unlock(&adev->lock);
3244
Naresh Tannirud7205b62014-06-20 02:54:48 +05303245exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003246 str = str_parms_to_str(reply);
3247 str_parms_destroy(query);
3248 str_parms_destroy(reply);
3249
3250 ALOGV("%s: exit: returns - %s", __func__, str);
3251 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252}
3253
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003254static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255{
3256 return 0;
3257}
3258
3259static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3260{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003261 int ret;
3262 struct audio_device *adev = (struct audio_device *)dev;
3263 pthread_mutex_lock(&adev->lock);
3264 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003265 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003266 pthread_mutex_unlock(&adev->lock);
3267 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268}
3269
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003270static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3271 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272{
3273 return -ENOSYS;
3274}
3275
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003276static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3277 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278{
3279 return -ENOSYS;
3280}
3281
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003282static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3283 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284{
3285 return -ENOSYS;
3286}
3287
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003288static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3289 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290{
3291 return -ENOSYS;
3292}
3293
3294static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3295{
3296 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 pthread_mutex_lock(&adev->lock);
3299 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003300 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003302 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3303 voice_is_in_call(adev)) {
3304 voice_stop_call(adev);
3305 adev->current_call_output = NULL;
3306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 }
3308 pthread_mutex_unlock(&adev->lock);
3309 return 0;
3310}
3311
3312static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3313{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003314 int ret;
3315
3316 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003317 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003318 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3319 pthread_mutex_unlock(&adev->lock);
3320
3321 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322}
3323
3324static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3325{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003326 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 return 0;
3328}
3329
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003330static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 const struct audio_config *config)
3332{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003333 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003335 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3336 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337}
3338
3339static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003340 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 audio_devices_t devices,
3342 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003343 struct audio_stream_in **stream_in,
3344 audio_input_flags_t flags __unused,
3345 const char *address __unused,
3346 audio_source_t source __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 struct audio_device *adev = (struct audio_device *)dev;
3349 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003350 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003351 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003352 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 *stream_in = NULL;
3355 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3356 return -EINVAL;
3357
3358 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003359
3360 if (!in) {
3361 ALOGE("failed to allocate input stream");
3362 return -ENOMEM;
3363 }
3364
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303365 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003366 stream_handle(%p) io_handle(%d)",__func__, config->sample_rate, config->channel_mask,
3367 devices, &in->stream, handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003369 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 in->stream.common.get_sample_rate = in_get_sample_rate;
3372 in->stream.common.set_sample_rate = in_set_sample_rate;
3373 in->stream.common.get_buffer_size = in_get_buffer_size;
3374 in->stream.common.get_channels = in_get_channels;
3375 in->stream.common.get_format = in_get_format;
3376 in->stream.common.set_format = in_set_format;
3377 in->stream.common.standby = in_standby;
3378 in->stream.common.dump = in_dump;
3379 in->stream.common.set_parameters = in_set_parameters;
3380 in->stream.common.get_parameters = in_get_parameters;
3381 in->stream.common.add_audio_effect = in_add_audio_effect;
3382 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3383 in->stream.set_gain = in_set_gain;
3384 in->stream.read = in_read;
3385 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3386
3387 in->device = devices;
3388 in->source = AUDIO_SOURCE_DEFAULT;
3389 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 in->standby = 1;
3391 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003392 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393
3394 /* Update config params with the requested sample rate and channels */
3395 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003396 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3397 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3398 is_low_latency = true;
3399#if LOW_LATENCY_CAPTURE_USE_CASE
3400 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3401#endif
3402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003405 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003407 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303408 if (adev->mode != AUDIO_MODE_IN_CALL) {
3409 ret = -EINVAL;
3410 goto err_open;
3411 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003412 if (config->sample_rate == 0)
3413 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3414 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3415 config->sample_rate != 8000) {
3416 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3417 ret = -EINVAL;
3418 goto err_open;
3419 }
3420 if (config->format == AUDIO_FORMAT_DEFAULT)
3421 config->format = AUDIO_FORMAT_PCM_16_BIT;
3422 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3423 config->format = AUDIO_FORMAT_PCM_16_BIT;
3424 ret = -EINVAL;
3425 goto err_open;
3426 }
3427
3428 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3429 in->config = pcm_config_afe_proxy_record;
3430 in->config.channels = channel_count;
3431 in->config.rate = config->sample_rate;
3432 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003433 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003434 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003435 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3436 ret = -EINVAL;
3437 goto err_open;
3438 }
3439 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003440 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003441 }
Mingming Yine62d7842013-10-25 16:26:03 -07003442 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003443 audio_extn_compr_cap_format_supported(config->format) &&
3444 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003445 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003446 } else {
3447 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003448 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003449 buffer_size = get_input_buffer_size(config->sample_rate,
3450 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003451 channel_count,
3452 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003453 in->config.period_size = buffer_size / frame_size;
3454 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003456 /* This stream could be for sound trigger lab,
3457 get sound trigger pcm if present */
3458 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303459 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003462 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003463 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464
3465err_open:
3466 free(in);
3467 *stream_in = NULL;
3468 return ret;
3469}
3470
3471static void adev_close_input_stream(struct audio_hw_device *dev,
3472 struct audio_stream_in *stream)
3473{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003474 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003475 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003476 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303477
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303478 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003479
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303480 /* Disable echo reference while closing input stream */
3481 platform_set_echo_reference(adev->platform, false);
3482
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003483 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303484 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003485 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303486 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003487 if (ret != 0)
3488 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3489 __func__, ret);
3490 } else
3491 in_standby(&stream->common);
3492
Mingming Yin7b762e72015-03-04 13:47:32 -08003493 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003494 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003495 audio_extn_ssr_deinit();
3496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
Mingming Yine62d7842013-10-25 16:26:03 -07003498 if(audio_extn_compr_cap_enabled() &&
3499 audio_extn_compr_cap_format_supported(in->config.format))
3500 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003501
3502 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 return;
3504}
3505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003506static int adev_dump(const audio_hw_device_t *device __unused,
3507 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508{
3509 return 0;
3510}
3511
3512static int adev_close(hw_device_t *device)
3513{
3514 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003515
3516 if (!adev)
3517 return 0;
3518
3519 pthread_mutex_lock(&adev_init_lock);
3520
3521 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003522 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003523 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003524 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003525 audio_route_free(adev->audio_route);
3526 free(adev->snd_dev_ref_cnt);
3527 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003528 free(device);
3529 adev = NULL;
3530 }
3531 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 return 0;
3533}
3534
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003535/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3536 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3537 * just that it _might_ work.
3538 */
3539static int period_size_is_plausible_for_low_latency(int period_size)
3540{
3541 switch (period_size) {
3542 case 160:
3543 case 240:
3544 case 320:
3545 case 480:
3546 return 1;
3547 default:
3548 return 0;
3549 }
3550}
3551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552static int adev_open(const hw_module_t *module, const char *name,
3553 hw_device_t **device)
3554{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003555 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003557 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3559
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003560 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003561 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003562 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003563 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003564 ALOGD("%s: returning existing instance of adev", __func__);
3565 ALOGD("%s: exit", __func__);
3566 pthread_mutex_unlock(&adev_init_lock);
3567 return 0;
3568 }
3569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 adev = calloc(1, sizeof(struct audio_device));
3571
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003572 if (!adev) {
3573 pthread_mutex_unlock(&adev_init_lock);
3574 return -ENOMEM;
3575 }
3576
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003577 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3580 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3581 adev->device.common.module = (struct hw_module_t *)module;
3582 adev->device.common.close = adev_close;
3583
3584 adev->device.init_check = adev_init_check;
3585 adev->device.set_voice_volume = adev_set_voice_volume;
3586 adev->device.set_master_volume = adev_set_master_volume;
3587 adev->device.get_master_volume = adev_get_master_volume;
3588 adev->device.set_master_mute = adev_set_master_mute;
3589 adev->device.get_master_mute = adev_get_master_mute;
3590 adev->device.set_mode = adev_set_mode;
3591 adev->device.set_mic_mute = adev_set_mic_mute;
3592 adev->device.get_mic_mute = adev_get_mic_mute;
3593 adev->device.set_parameters = adev_set_parameters;
3594 adev->device.get_parameters = adev_get_parameters;
3595 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3596 adev->device.open_output_stream = adev_open_output_stream;
3597 adev->device.close_output_stream = adev_close_output_stream;
3598 adev->device.open_input_stream = adev_open_input_stream;
3599 adev->device.close_input_stream = adev_close_input_stream;
3600 adev->device.dump = adev_dump;
3601
3602 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003604 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003605 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003608 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003609 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003610 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3611 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003612 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003613 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003614 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003615 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003616 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303617
3618 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3619 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003621 adev->platform = platform_init(adev);
3622 if (!adev->platform) {
3623 free(adev->snd_dev_ref_cnt);
3624 free(adev);
3625 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3626 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003627 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003628 return -EINVAL;
3629 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003630
Naresh Tanniru4c630392014-05-12 01:05:52 +05303631 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3632
Eric Laurentc4aef752013-09-12 17:45:53 -07003633 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3634 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3635 if (adev->visualizer_lib == NULL) {
3636 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3637 } else {
3638 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3639 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003640 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003641 "visualizer_hal_start_output");
3642 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003643 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003644 "visualizer_hal_stop_output");
3645 }
3646 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003647 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003648 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003649
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003650 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3651 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3652 if (adev->offload_effects_lib == NULL) {
3653 ALOGE("%s: DLOPEN failed for %s", __func__,
3654 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3655 } else {
3656 ALOGV("%s: DLOPEN successful for %s", __func__,
3657 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3658 adev->offload_effects_start_output =
3659 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3660 "offload_effects_bundle_hal_start_output");
3661 adev->offload_effects_stop_output =
3662 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3663 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003664 adev->offload_effects_set_hpx_state =
3665 (int (*)(bool))dlsym(adev->offload_effects_lib,
3666 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003667 }
3668 }
3669
Mingming Yin514a8bc2014-07-29 15:22:21 -07003670 adev->bt_wb_speech_enabled = false;
3671
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003672 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 *device = &adev->device.common;
3674
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003675 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3676 &adev->streams_output_cfg_list);
3677
Kiran Kandi910e1862013-10-29 13:29:42 -07003678 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003679
3680 char value[PROPERTY_VALUE_MAX];
3681 int trial;
3682 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3683 trial = atoi(value);
3684 if (period_size_is_plausible_for_low_latency(trial)) {
3685 pcm_config_low_latency.period_size = trial;
3686 pcm_config_low_latency.start_threshold = trial / 4;
3687 pcm_config_low_latency.avail_min = trial / 4;
3688 configured_low_latency_capture_period_size = trial;
3689 }
3690 }
3691 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3692 trial = atoi(value);
3693 if (period_size_is_plausible_for_low_latency(trial)) {
3694 configured_low_latency_capture_period_size = trial;
3695 }
3696 }
3697
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003698 pthread_mutex_unlock(&adev_init_lock);
3699
Eric Laurent994a6932013-07-17 11:51:42 -07003700 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 return 0;
3702}
3703
3704static struct hw_module_methods_t hal_module_methods = {
3705 .open = adev_open,
3706};
3707
3708struct audio_module HAL_MODULE_INFO_SYM = {
3709 .common = {
3710 .tag = HARDWARE_MODULE_TAG,
3711 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3712 .hal_api_version = HARDWARE_HAL_API_VERSION,
3713 .id = AUDIO_HARDWARE_MODULE_ID,
3714 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003715 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 .methods = &hal_module_methods,
3717 },
3718};