blob: c2d340092231bb04f86d0326bfed7c921d4a044a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800193 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700194 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
195 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
196 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800197 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
198 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
199 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
200
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700201 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
202 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700203 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
204 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700205
206 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
207 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700208};
209
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700210static const audio_usecase_t offload_usecases[] = {
211 USECASE_AUDIO_PLAYBACK_OFFLOAD,
212#ifdef MULTIPLE_OFFLOAD_ENABLED
213 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
214 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
215 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
221#endif
222};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800223
224#define STRING_TO_ENUM(string) { #string, string }
225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800226struct string_to_enum {
227 const char *name;
228 uint32_t value;
229};
230
231static const struct string_to_enum out_channels_name_to_enum_table[] = {
232 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700233 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
239};
240
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700241static const struct string_to_enum out_formats_name_to_enum_table[] = {
242 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
243 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
244 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
245};
246
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700247static struct audio_device *adev = NULL;
248static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700249static unsigned int audio_device_ref_count;
250
Haynes Mathew George5191a852013-09-11 14:19:36 -0700251static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800252
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800253static int check_and_set_gapless_mode(struct audio_device *adev) {
254
255
256 char value[PROPERTY_VALUE_MAX] = {0};
257 bool gapless_enabled = false;
258 const char *mixer_ctl_name = "Compress Gapless Playback";
259 struct mixer_ctl *ctl;
260
261 ALOGV("%s:", __func__);
262 property_get("audio.offload.gapless.enabled", value, NULL);
263 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
264
265 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
266 if (!ctl) {
267 ALOGE("%s: Could not get ctl for mixer cmd - %s",
268 __func__, mixer_ctl_name);
269 return -EINVAL;
270 }
271
272 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
273 ALOGE("%s: Could not set gapless mode %d",
274 __func__, gapless_enabled);
275 return -EINVAL;
276 }
277 return 0;
278}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700279
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700280static bool is_supported_format(audio_format_t format)
281{
Eric Laurent86e17132013-09-12 17:49:30 -0700282 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530283 format == AUDIO_FORMAT_AAC_LC ||
284 format == AUDIO_FORMAT_AAC_HE_V1 ||
285 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800286 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700287 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
288 format == AUDIO_FORMAT_FLAC)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800289 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700290
291 return false;
292}
293
294static int get_snd_codec_id(audio_format_t format)
295{
296 int id = 0;
297
Ashish Jainf9b78162014-08-25 20:36:25 +0530298 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700299 case AUDIO_FORMAT_MP3:
300 id = SND_AUDIOCODEC_MP3;
301 break;
302 case AUDIO_FORMAT_AAC:
303 id = SND_AUDIOCODEC_AAC;
304 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800306 id = SND_AUDIOCODEC_PCM;
307 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700308 case AUDIO_FORMAT_FLAC:
309 id = SND_AUDIOCODEC_FLAC;
310 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700311 default:
Mingming Yin90310102013-11-13 16:57:00 -0800312 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700313 }
314
315 return id;
316}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800317
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530318int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530319{
320 int snd_scard_state;
321
322 if (!adev)
323 return SND_CARD_STATE_OFFLINE;
324
325 pthread_mutex_lock(&adev->snd_card_status.lock);
326 snd_scard_state = adev->snd_card_status.state;
327 pthread_mutex_unlock(&adev->snd_card_status.lock);
328
329 return snd_scard_state;
330}
331
332static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
333{
334 if (!adev)
335 return -ENOSYS;
336
337 pthread_mutex_lock(&adev->snd_card_status.lock);
338 adev->snd_card_status.state = snd_scard_state;
339 pthread_mutex_unlock(&adev->snd_card_status.lock);
340
341 return 0;
342}
343
Avinash Vaish71a8b972014-07-24 15:36:33 +0530344static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
345 struct audio_usecase *uc_info)
346{
347 struct listnode *node;
348 struct audio_usecase *usecase;
349
350 if (uc_info == NULL)
351 return -EINVAL;
352
353 /* Re-route all voice usecases on the shared backend other than the
354 specified usecase to new snd devices */
355 list_for_each(node, &adev->usecase_list) {
356 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800357 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530358 enable_audio_route(adev, usecase);
359 }
360 return 0;
361}
362
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700363int pcm_ioctl(struct pcm *pcm, int request, ...)
364{
365 va_list ap;
366 void * arg;
367 int pcm_fd = *(int*)pcm;
368
369 va_start(ap, request);
370 arg = va_arg(ap, void *);
371 va_end(ap);
372
373 return ioctl(pcm_fd, request, arg);
374}
375
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700376int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700377 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800378{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700379 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700380 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800381
382 if (usecase == NULL)
383 return -EINVAL;
384
385 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
386
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800387 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700388 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800389 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700390 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800391
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800392#ifdef DS1_DOLBY_DAP_ENABLED
393 audio_extn_dolby_set_dmid(adev);
394 audio_extn_dolby_set_endpoint(adev);
395#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700396 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700397 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530398 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700399 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700400 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800401 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700402 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700403 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
404 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800405 ALOGV("%s: exit", __func__);
406 return 0;
407}
408
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700409int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700410 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800411{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700413 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800414
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530415 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800416 return -EINVAL;
417
418 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700419 if (usecase->type == PCM_CAPTURE)
420 snd_device = usecase->in_snd_device;
421 else
422 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800423 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
426 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700427 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530428 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429 ALOGV("%s: exit", __func__);
430 return 0;
431}
432
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700433int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700434 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700436 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
437
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800438 if (snd_device < SND_DEVICE_MIN ||
439 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800440 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800441 return -EINVAL;
442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700443
444 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700445
446 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
447 ALOGE("%s: Invalid sound device returned", __func__);
448 return -EINVAL;
449 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700450 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700451 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700452 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700453 return 0;
454 }
455
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700456 if (audio_extn_spkr_prot_is_enabled())
457 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700458 /* start usb playback thread */
459 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
460 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
461 audio_extn_usb_start_playback(adev);
462
463 /* start usb capture thread */
464 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
465 audio_extn_usb_start_capture(adev);
466
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800467 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
468 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700469 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700470 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
471 adev->snd_dev_ref_cnt[snd_device]--;
472 return -EINVAL;
473 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200474 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800475 if (audio_extn_spkr_prot_start_processing(snd_device)) {
476 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200477 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800478 return -EINVAL;
479 }
480 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700481 ALOGV("%s: snd_device(%d: %s)", __func__,
482 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700483 /* due to the possibility of calibration overwrite between listen
484 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700485 audio_extn_sound_trigger_update_device_status(snd_device,
486 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530487 audio_extn_listen_update_device_status(snd_device,
488 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700489 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700490 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700491 audio_extn_sound_trigger_update_device_status(snd_device,
492 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530493 audio_extn_listen_update_device_status(snd_device,
494 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700495 return -EINVAL;
496 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300497 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700498 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800500 return 0;
501}
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700504 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800505{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700506 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
507
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800508 if (snd_device < SND_DEVICE_MIN ||
509 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800510 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800511 return -EINVAL;
512 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
514 ALOGE("%s: device ref cnt is already 0", __func__);
515 return -EINVAL;
516 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700517
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700518 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700519
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700520 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
521 ALOGE("%s: Invalid sound device returned", __func__);
522 return -EINVAL;
523 }
524
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700525 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700526 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700527 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800528 /* exit usb play back thread */
529 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
530 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
531 audio_extn_usb_stop_playback();
532
533 /* exit usb capture thread */
534 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700535 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800536
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800537 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
538 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700539 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700540 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300541 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700542 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300543 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700544
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200545 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700546 audio_extn_sound_trigger_update_device_status(snd_device,
547 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530548 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800549 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700550 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 return 0;
553}
554
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700555static void check_usecases_codec_backend(struct audio_device *adev,
556 struct audio_usecase *uc_info,
557 snd_device_t snd_device)
558{
559 struct listnode *node;
560 struct audio_usecase *usecase;
561 bool switch_device[AUDIO_USECASE_MAX];
562 int i, num_uc_to_switch = 0;
563
564 /*
565 * This function is to make sure that all the usecases that are active on
566 * the hardware codec backend are always routed to any one device that is
567 * handled by the hardware codec.
568 * For example, if low-latency and deep-buffer usecases are currently active
569 * on speaker and out_set_parameters(headset) is received on low-latency
570 * output, then we have to make sure deep-buffer is also switched to headset,
571 * because of the limitation that both the devices cannot be enabled
572 * at the same time as they share the same backend.
573 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700574 /*
575 * This call is to check if we need to force routing for a particular stream
576 * If there is a backend configuration change for the device when a
577 * new stream starts, then ADM needs to be closed and re-opened with the new
578 * configuraion. This call check if we need to re-route all the streams
579 * associated with the backend. Touch tone + 24 bit playback.
580 */
581 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
582
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700583 /* Disable all the usecases on the shared backend other than the
584 specified usecase */
585 for (i = 0; i < AUDIO_USECASE_MAX; i++)
586 switch_device[i] = false;
587
588 list_for_each(node, &adev->usecase_list) {
589 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800590 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700591 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700592 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
594 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
595 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700596 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700597 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700598 switch_device[usecase->id] = true;
599 num_uc_to_switch++;
600 }
601 }
602
603 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700604 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530606 /* Make sure the previous devices to be disabled first and then enable the
607 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 list_for_each(node, &adev->usecase_list) {
609 usecase = node_to_item(node, struct audio_usecase, list);
610 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700611 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 }
613 }
614
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700615 list_for_each(node, &adev->usecase_list) {
616 usecase = node_to_item(node, struct audio_usecase, list);
617 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700618 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700619 }
620 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 /* Re-route all the usecases on the shared backend other than the
623 specified usecase to new snd devices */
624 list_for_each(node, &adev->usecase_list) {
625 usecase = node_to_item(node, struct audio_usecase, list);
626 /* Update the out_snd_device only before enabling the audio route */
627 if (switch_device[usecase->id] ) {
628 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800629 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530630 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700631 }
632 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 }
634}
635
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700636static void check_and_route_capture_usecases(struct audio_device *adev,
637 struct audio_usecase *uc_info,
638 snd_device_t snd_device)
639{
640 struct listnode *node;
641 struct audio_usecase *usecase;
642 bool switch_device[AUDIO_USECASE_MAX];
643 int i, num_uc_to_switch = 0;
644
645 /*
646 * This function is to make sure that all the active capture usecases
647 * are always routed to the same input sound device.
648 * For example, if audio-record and voice-call usecases are currently
649 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
650 * is received for voice call then we have to make sure that audio-record
651 * usecase is also switched to earpiece i.e. voice-dmic-ef,
652 * because of the limitation that two devices cannot be enabled
653 * at the same time if they share the same backend.
654 */
655 for (i = 0; i < AUDIO_USECASE_MAX; i++)
656 switch_device[i] = false;
657
658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800660 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700661 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700662 usecase->in_snd_device != snd_device &&
663 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700664 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
665 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700666 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700667 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700668 switch_device[usecase->id] = true;
669 num_uc_to_switch++;
670 }
671 }
672
673 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700674 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700675
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530676 /* Make sure the previous devices to be disabled first and then enable the
677 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700678 list_for_each(node, &adev->usecase_list) {
679 usecase = node_to_item(node, struct audio_usecase, list);
680 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700681 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800682 }
683 }
684
685 list_for_each(node, &adev->usecase_list) {
686 usecase = node_to_item(node, struct audio_usecase, list);
687 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700688 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700689 }
690 }
691
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700692 /* Re-route all the usecases on the shared backend other than the
693 specified usecase to new snd devices */
694 list_for_each(node, &adev->usecase_list) {
695 usecase = node_to_item(node, struct audio_usecase, list);
696 /* Update the in_snd_device only before enabling the audio route */
697 if (switch_device[usecase->id] ) {
698 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800699 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530700 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700701 }
702 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 }
704}
705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800706/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700707static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800708{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700709 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700710 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800711
712 switch (channels) {
713 /*
714 * Do not handle stereo output in Multi-channel cases
715 * Stereo case is handled in normal playback path
716 */
717 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700718 ALOGV("%s: HDMI supports Quad and 5.1", __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;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800724 break;
725 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700726 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
727 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
728 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
729 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
730 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
731 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
732 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800733 break;
734 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700735 ALOGE("HDMI does not support multi channel playback");
736 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800737 break;
738 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700739 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800740}
741
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700742static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
743{
744 struct audio_usecase *usecase;
745 struct listnode *node;
746
747 list_for_each(node, &adev->usecase_list) {
748 usecase = node_to_item(node, struct audio_usecase, list);
749 if (usecase->type == VOICE_CALL) {
750 ALOGV("%s: usecase id %d", __func__, usecase->id);
751 return usecase->id;
752 }
753 }
754 return USECASE_INVALID;
755}
756
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700757struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700758 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759{
760 struct audio_usecase *usecase;
761 struct listnode *node;
762
763 list_for_each(node, &adev->usecase_list) {
764 usecase = node_to_item(node, struct audio_usecase, list);
765 if (usecase->id == uc_id)
766 return usecase;
767 }
768 return NULL;
769}
770
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700771int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800773 snd_device_t out_snd_device = SND_DEVICE_NONE;
774 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700775 struct audio_usecase *usecase = NULL;
776 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800777 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800778 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800779 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800780 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700783 usecase = get_usecase_from_list(adev, uc_id);
784 if (usecase == NULL) {
785 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
786 return -EINVAL;
787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800788
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800789 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800790 (usecase->type == VOIP_CALL) ||
791 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700792 out_snd_device = platform_get_output_snd_device(adev->platform,
793 usecase->stream.out->devices);
794 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795 usecase->devices = usecase->stream.out->devices;
796 } else {
797 /*
798 * If the voice call is active, use the sound devices of voice call usecase
799 * so that it would not result any device switch. All the usecases will
800 * be switched to new device when select_devices() is called for voice call
801 * usecase. This is to avoid switching devices for voice call when
802 * check_usecases_codec_backend() is called below.
803 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700804 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700805 vc_usecase = get_usecase_from_list(adev,
806 get_voice_usecase_id_from_list(adev));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700807 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
808 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700809 in_snd_device = vc_usecase->in_snd_device;
810 out_snd_device = vc_usecase->out_snd_device;
811 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800812 } else if (voice_extn_compress_voip_is_active(adev)) {
813 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700814 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530815 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700816 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800817 in_snd_device = voip_usecase->in_snd_device;
818 out_snd_device = voip_usecase->out_snd_device;
819 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800820 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800821 hfp_ucid = audio_extn_hfp_get_usecase();
822 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700823 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800824 in_snd_device = hfp_usecase->in_snd_device;
825 out_snd_device = hfp_usecase->out_snd_device;
826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 }
828 if (usecase->type == PCM_PLAYBACK) {
829 usecase->devices = usecase->stream.out->devices;
830 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700831 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700832 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700834 if (usecase->stream.out == adev->primary_output &&
835 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800836 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
837 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700838 select_devices(adev, adev->active_input->usecase);
839 }
840 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700841 } else if (usecase->type == PCM_CAPTURE) {
842 usecase->devices = usecase->stream.in->device;
843 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700844 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700845 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530846 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
847 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
848 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
849 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700850 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800851 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700852 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
853 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700854 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700855 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 }
858 }
859
860 if (out_snd_device == usecase->out_snd_device &&
861 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862 return 0;
863 }
864
sangwoobc677242013-08-08 16:53:43 +0900865 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 out_snd_device, platform_get_snd_device_name(out_snd_device),
867 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800869 /*
870 * Limitation: While in call, to do a device switch we need to disable
871 * and enable both RX and TX devices though one of them is same as current
872 * device.
873 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700874 if ((usecase->type == VOICE_CALL) &&
875 (usecase->in_snd_device != SND_DEVICE_NONE) &&
876 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700877 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800878 }
879
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 /* Disable current sound devices */
881 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700882 disable_audio_route(adev, usecase);
883 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800884 }
885
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700887 disable_audio_route(adev, usecase);
888 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800889 }
890
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800891 /* Applicable only on the targets that has external modem.
892 * New device information should be sent to modem before enabling
893 * the devices to reduce in-call device switch time.
894 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700895 if ((usecase->type == VOICE_CALL) &&
896 (usecase->in_snd_device != SND_DEVICE_NONE) &&
897 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800898 status = platform_switch_voice_call_enable_device_config(adev->platform,
899 out_snd_device,
900 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700901 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800902
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 /* Enable new sound devices */
904 if (out_snd_device != SND_DEVICE_NONE) {
905 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
906 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700907 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 }
909
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700910 if (in_snd_device != SND_DEVICE_NONE) {
911 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700912 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700913 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700914
Avinash Vaish71a8b972014-07-24 15:36:33 +0530915 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700916 status = platform_switch_voice_call_device_post(adev->platform,
917 out_snd_device,
918 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530919 enable_audio_route_for_voice_usecases(adev, usecase);
920 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800921
sangwoo170731f2013-06-08 15:36:36 +0900922 usecase->in_snd_device = in_snd_device;
923 usecase->out_snd_device = out_snd_device;
924
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530925 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700926 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530927 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700928 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530929 usecase->stream.out->flags,
930 usecase->stream.out->format,
931 usecase->stream.out->sample_rate,
932 usecase->stream.out->bit_width,
933 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700934 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530935 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700936
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700937 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900938
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800939 /* Applicable only on the targets that has external modem.
940 * Enable device command should be sent to modem only after
941 * enabling voice call mixer controls
942 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700943 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800944 status = platform_switch_voice_call_usecase_route_post(adev->platform,
945 out_snd_device,
946 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530947 ALOGD("%s: done",__func__);
948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800949 return status;
950}
951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952static int stop_input_stream(struct stream_in *in)
953{
954 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955 struct audio_usecase *uc_info;
956 struct audio_device *adev = in->dev;
957
Eric Laurentc8400632013-02-14 19:04:54 -0800958 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959
Eric Laurent994a6932013-07-17 11:51:42 -0700960 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700961 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962 uc_info = get_usecase_from_list(adev, in->usecase);
963 if (uc_info == NULL) {
964 ALOGE("%s: Could not find the usecase (%d) in the list",
965 __func__, in->usecase);
966 return -EINVAL;
967 }
968
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800969 /* Close in-call recording streams */
970 voice_check_and_stop_incall_rec_usecase(adev, in);
971
Eric Laurent150dbfe2013-02-27 14:31:02 -0800972 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700973 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974
975 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700976 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800978 list_remove(&uc_info->list);
979 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980
Eric Laurent994a6932013-07-17 11:51:42 -0700981 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982 return ret;
983}
984
985int start_input_stream(struct stream_in *in)
986{
987 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800988 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989 struct audio_usecase *uc_info;
990 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530991 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992
Mingming Yine62d7842013-10-25 16:26:03 -0700993 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530994 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
995 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700996
Naresh Tanniru80659832014-06-04 18:17:56 +0530997
998 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +0530999 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301000 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301001 goto error_config;
1002 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301003
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001004 /* Check if source matches incall recording usecase criteria */
1005 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1006 if (ret)
1007 goto error_config;
1008 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001009 ALOGD("%s: Updated usecase(%d: %s)",
1010 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001011
Eric Laurentb23d5282013-05-14 15:27:20 -07001012 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 if (in->pcm_device_id < 0) {
1014 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1015 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001016 ret = -EINVAL;
1017 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019
1020 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001022
1023 if (!uc_info) {
1024 ret = -ENOMEM;
1025 goto error_config;
1026 }
1027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 uc_info->id = in->usecase;
1029 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001030 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 uc_info->devices = in->device;
1032 uc_info->in_snd_device = SND_DEVICE_NONE;
1033 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001035 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301036 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038
Eric Laurentc8400632013-02-14 19:04:54 -08001039 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001040 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1041
1042 unsigned int flags = PCM_IN;
1043 unsigned int pcm_open_retry_count = 0;
1044
1045 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1046 flags |= PCM_MMAP | PCM_NOIRQ;
1047 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1048 }
1049
1050 while (1) {
1051 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1052 flags, &in->config);
1053 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1054 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1055 if (in->pcm != NULL) {
1056 pcm_close(in->pcm);
1057 in->pcm = NULL;
1058 }
1059 if (pcm_open_retry_count-- == 0) {
1060 ret = -EIO;
1061 goto error_open;
1062 }
1063 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1064 continue;
1065 }
1066 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301068 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301069
Eric Laurent994a6932013-07-17 11:51:42 -07001070 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001071 return ret;
1072
1073error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301075 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001076
1077error_config:
1078 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001080
1081 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082}
1083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001084/* must be called with out->lock locked */
1085static int send_offload_cmd_l(struct stream_out* out, int command)
1086{
1087 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1088
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001089 if (!cmd) {
1090 ALOGE("failed to allocate mem for command 0x%x", command);
1091 return -ENOMEM;
1092 }
1093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001094 ALOGVV("%s %d", __func__, command);
1095
1096 cmd->cmd = command;
1097 list_add_tail(&out->offload_cmd_list, &cmd->node);
1098 pthread_cond_signal(&out->offload_cond);
1099 return 0;
1100}
1101
1102/* must be called iwth out->lock locked */
1103static void stop_compressed_output_l(struct stream_out *out)
1104{
1105 out->offload_state = OFFLOAD_STATE_IDLE;
1106 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001107 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001108 if (out->compr != NULL) {
1109 compress_stop(out->compr);
1110 while (out->offload_thread_blocked) {
1111 pthread_cond_wait(&out->cond, &out->lock);
1112 }
1113 }
1114}
1115
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001116bool is_offload_usecase(audio_usecase_t uc_id)
1117{
1118 unsigned int i;
1119 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1120 if (uc_id == offload_usecases[i])
1121 return true;
1122 }
1123 return false;
1124}
1125
1126static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1127{
1128 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1129 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1130 char value[PROPERTY_VALUE_MAX] = {0};
1131
1132 property_get("audio.offload.multiple.enabled", value, NULL);
1133 if (!(atoi(value) || !strncmp("true", value, 4)))
1134 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1135
1136 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1137 for (i = 0; i < num_usecase; i++) {
1138 if (!(adev->offload_usecases_state & (0x1<<i))) {
1139 adev->offload_usecases_state |= 0x1 << i;
1140 ret = offload_usecases[i];
1141 break;
1142 }
1143 }
1144 ALOGV("%s: offload usecase is %d", __func__, ret);
1145 return ret;
1146}
1147
1148static void free_offload_usecase(struct audio_device *adev,
1149 audio_usecase_t uc_id)
1150{
1151 unsigned int i;
1152 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1153 if (offload_usecases[i] == uc_id) {
1154 adev->offload_usecases_state &= ~(0x1<<i);
1155 break;
1156 }
1157 }
1158 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1159}
1160
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001161static void *offload_thread_loop(void *context)
1162{
1163 struct stream_out *out = (struct stream_out *) context;
1164 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001165 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001166
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001167 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1168 set_sched_policy(0, SP_FOREGROUND);
1169 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1170
1171 ALOGV("%s", __func__);
1172 pthread_mutex_lock(&out->lock);
1173 for (;;) {
1174 struct offload_cmd *cmd = NULL;
1175 stream_callback_event_t event;
1176 bool send_callback = false;
1177
1178 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1179 __func__, list_empty(&out->offload_cmd_list),
1180 out->offload_state);
1181 if (list_empty(&out->offload_cmd_list)) {
1182 ALOGV("%s SLEEPING", __func__);
1183 pthread_cond_wait(&out->offload_cond, &out->lock);
1184 ALOGV("%s RUNNING", __func__);
1185 continue;
1186 }
1187
1188 item = list_head(&out->offload_cmd_list);
1189 cmd = node_to_item(item, struct offload_cmd, node);
1190 list_remove(item);
1191
1192 ALOGVV("%s STATE %d CMD %d out->compr %p",
1193 __func__, out->offload_state, cmd->cmd, out->compr);
1194
1195 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1196 free(cmd);
1197 break;
1198 }
1199
1200 if (out->compr == NULL) {
1201 ALOGE("%s: Compress handle is NULL", __func__);
1202 pthread_cond_signal(&out->cond);
1203 continue;
1204 }
1205 out->offload_thread_blocked = true;
1206 pthread_mutex_unlock(&out->lock);
1207 send_callback = false;
1208 switch(cmd->cmd) {
1209 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001210 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001211 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001212 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001213 send_callback = true;
1214 event = STREAM_CBK_EVENT_WRITE_READY;
1215 break;
1216 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001217 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301218 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001219 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301220 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001221 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301222 if (ret < 0)
1223 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301224 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301225 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001226 compress_drain(out->compr);
1227 else
1228 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301229 if (ret != -ENETRESET) {
1230 send_callback = true;
1231 event = STREAM_CBK_EVENT_DRAIN_READY;
1232 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1233 } else
1234 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001235 break;
1236 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001237 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001238 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001239 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001240 send_callback = true;
1241 event = STREAM_CBK_EVENT_DRAIN_READY;
1242 break;
1243 default:
1244 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1245 break;
1246 }
1247 pthread_mutex_lock(&out->lock);
1248 out->offload_thread_blocked = false;
1249 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001250 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001251 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001252 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001253 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001254 free(cmd);
1255 }
1256
1257 pthread_cond_signal(&out->cond);
1258 while (!list_empty(&out->offload_cmd_list)) {
1259 item = list_head(&out->offload_cmd_list);
1260 list_remove(item);
1261 free(node_to_item(item, struct offload_cmd, node));
1262 }
1263 pthread_mutex_unlock(&out->lock);
1264
1265 return NULL;
1266}
1267
1268static int create_offload_callback_thread(struct stream_out *out)
1269{
1270 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1271 list_init(&out->offload_cmd_list);
1272 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1273 offload_thread_loop, out);
1274 return 0;
1275}
1276
1277static int destroy_offload_callback_thread(struct stream_out *out)
1278{
1279 pthread_mutex_lock(&out->lock);
1280 stop_compressed_output_l(out);
1281 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1282
1283 pthread_mutex_unlock(&out->lock);
1284 pthread_join(out->offload_thread, (void **) NULL);
1285 pthread_cond_destroy(&out->offload_cond);
1286
1287 return 0;
1288}
1289
Eric Laurent07eeafd2013-10-06 12:52:49 -07001290static bool allow_hdmi_channel_config(struct audio_device *adev)
1291{
1292 struct listnode *node;
1293 struct audio_usecase *usecase;
1294 bool ret = true;
1295
1296 list_for_each(node, &adev->usecase_list) {
1297 usecase = node_to_item(node, struct audio_usecase, list);
1298 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1299 /*
1300 * If voice call is already existing, do not proceed further to avoid
1301 * disabling/enabling both RX and TX devices, CSD calls, etc.
1302 * Once the voice call done, the HDMI channels can be configured to
1303 * max channels of remaining use cases.
1304 */
1305 if (usecase->id == USECASE_VOICE_CALL) {
1306 ALOGD("%s: voice call is active, no change in HDMI channels",
1307 __func__);
1308 ret = false;
1309 break;
1310 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1311 ALOGD("%s: multi channel playback is active, "
1312 "no change in HDMI channels", __func__);
1313 ret = false;
1314 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001315 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001316 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001317 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1318 ", no change in HDMI channels", __func__,
1319 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001320 ret = false;
1321 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001322 }
1323 }
1324 }
1325 return ret;
1326}
1327
1328static int check_and_set_hdmi_channels(struct audio_device *adev,
1329 unsigned int channels)
1330{
1331 struct listnode *node;
1332 struct audio_usecase *usecase;
1333
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001334 unsigned int supported_channels = platform_edid_get_max_channels(
1335 adev->platform);
1336 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001337 /* Check if change in HDMI channel config is allowed */
1338 if (!allow_hdmi_channel_config(adev))
1339 return 0;
1340
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001341 if (channels > supported_channels)
1342 channels = supported_channels;
1343
Eric Laurent07eeafd2013-10-06 12:52:49 -07001344 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001345 ALOGD("%s: Requested channels are same as current channels(%d)",
1346 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001347 return 0;
1348 }
1349
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001350 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001351 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001352 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001353 adev->cur_hdmi_channels = channels;
1354
1355 /*
1356 * Deroute all the playback streams routed to HDMI so that
1357 * the back end is deactivated. Note that backend will not
1358 * be deactivated if any one stream is connected to it.
1359 */
1360 list_for_each(node, &adev->usecase_list) {
1361 usecase = node_to_item(node, struct audio_usecase, list);
1362 if (usecase->type == PCM_PLAYBACK &&
1363 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001364 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001365 }
1366 }
1367
1368 /*
1369 * Enable all the streams disabled above. Now the HDMI backend
1370 * will be activated with new channel configuration
1371 */
1372 list_for_each(node, &adev->usecase_list) {
1373 usecase = node_to_item(node, struct audio_usecase, list);
1374 if (usecase->type == PCM_PLAYBACK &&
1375 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001376 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001377 }
1378 }
1379
1380 return 0;
1381}
1382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383static int stop_output_stream(struct stream_out *out)
1384{
1385 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001386 struct audio_usecase *uc_info;
1387 struct audio_device *adev = out->dev;
1388
Eric Laurent994a6932013-07-17 11:51:42 -07001389 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001390 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391 uc_info = get_usecase_from_list(adev, out->usecase);
1392 if (uc_info == NULL) {
1393 ALOGE("%s: Could not find the usecase (%d) in the list",
1394 __func__, out->usecase);
1395 return -EINVAL;
1396 }
1397
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001398 if (is_offload_usecase(out->usecase) &&
1399 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001400 if (adev->visualizer_stop_output != NULL)
1401 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001402
1403 audio_extn_dts_remove_state_notifier_node(out->usecase);
1404
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001405 if (adev->offload_effects_stop_output != NULL)
1406 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1407 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001408
Eric Laurent150dbfe2013-02-27 14:31:02 -08001409 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001410 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411
1412 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001413 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001414
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001415 list_remove(&uc_info->list);
1416 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001418 if (is_offload_usecase(out->usecase) &&
1419 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1420 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1421 ALOGV("Disable passthrough , reset mixer to pcm");
1422 /* NO_PASSTHROUGH */
1423 out->compr_config.codec->compr_passthr = 0;
1424 audio_extn_dolby_set_hdmi_config(adev, out);
1425 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1426 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001427 /* Must be called after removing the usecase from list */
1428 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1429 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1430
Eric Laurent994a6932013-07-17 11:51:42 -07001431 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 return ret;
1433}
1434
1435int start_output_stream(struct stream_out *out)
1436{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001438 int sink_channels = 0;
1439 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 struct audio_usecase *uc_info;
1441 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301442 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001444 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1445 ret = -EINVAL;
1446 goto error_config;
1447 }
1448
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301449 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1450 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1451 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301452
Naresh Tanniru80659832014-06-04 18:17:56 +05301453 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301454 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301455 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301456 goto error_config;
1457 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301458
Eric Laurentb23d5282013-05-14 15:27:20 -07001459 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460 if (out->pcm_device_id < 0) {
1461 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1462 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001463 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001464 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 }
1466
1467 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001468
1469 if (!uc_info) {
1470 ret = -ENOMEM;
1471 goto error_config;
1472 }
1473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474 uc_info->id = out->usecase;
1475 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001476 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 uc_info->devices = out->devices;
1478 uc_info->in_snd_device = SND_DEVICE_NONE;
1479 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001480 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001481 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001482 if (is_offload_usecase(out->usecase)) {
1483 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001484 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1485 }
1486 }
Mingming Yin9c041392014-05-01 15:37:31 -07001487 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1488 if (!strncmp("true", prop_value, 4)) {
1489 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001490 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1491 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001492 check_and_set_hdmi_channels(adev, sink_channels);
1493 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001494 if (is_offload_usecase(out->usecase)) {
1495 unsigned int ch_count = out->compr_config.codec->ch_in;
1496 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1497 /* backend channel config for passthrough stream is stereo */
1498 ch_count = 2;
1499 check_and_set_hdmi_channels(adev, ch_count);
1500 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001501 check_and_set_hdmi_channels(adev, out->config.channels);
1502 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001503 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001504 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001505 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 select_devices(adev, out->usecase);
1508
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001509 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1510 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001511 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001512 unsigned int flags = PCM_OUT;
1513 unsigned int pcm_open_retry_count = 0;
1514 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1515 flags |= PCM_MMAP | PCM_NOIRQ;
1516 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1517 } else
1518 flags |= PCM_MONOTONIC;
1519
1520 while (1) {
1521 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1522 flags, &out->config);
1523 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1524 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1525 if (out->pcm != NULL) {
1526 pcm_close(out->pcm);
1527 out->pcm = NULL;
1528 }
1529 if (pcm_open_retry_count-- == 0) {
1530 ret = -EIO;
1531 goto error_open;
1532 }
1533 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1534 continue;
1535 }
1536 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001537 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001538 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1539 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001541 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1542 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001544 out->compr = compress_open(adev->snd_card,
1545 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001546 COMPRESS_IN, &out->compr_config);
1547 if (out->compr && !is_compress_ready(out->compr)) {
1548 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1549 compress_close(out->compr);
1550 out->compr = NULL;
1551 ret = -EIO;
1552 goto error_open;
1553 }
1554 if (out->offload_callback)
1555 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001556
Fred Oh3f43e742015-03-04 18:42:34 -08001557 /* Since small bufs uses blocking writes, a write will be blocked
1558 for the default max poll time (20s) in the event of an SSR.
1559 Reduce the poll time to observe and deal with SSR faster.
1560 */
1561 if (out->use_small_bufs) {
1562 compress_set_max_poll_wait(out->compr, 1000);
1563 }
1564
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001565 audio_extn_dts_create_state_notifier_node(out->usecase);
1566 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1567 popcount(out->channel_mask),
1568 out->playback_started);
1569
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001570#ifdef DS1_DOLBY_DDP_ENABLED
1571 if (audio_extn_is_dolby_format(out->format))
1572 audio_extn_dolby_send_ddp_endp_params(adev);
1573#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001574 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1575 if (adev->visualizer_start_output != NULL)
1576 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1577 if (adev->offload_effects_start_output != NULL)
1578 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001579 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001580 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001581 }
Eric Laurent994a6932013-07-17 11:51:42 -07001582 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001584error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001585 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001586error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001587 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588}
1589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590static int check_input_parameters(uint32_t sample_rate,
1591 audio_format_t format,
1592 int channel_count)
1593{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001594 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001596 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001597 !voice_extn_compress_voip_is_format_supported(format) &&
1598 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001599
1600 switch (channel_count) {
1601 case 1:
1602 case 2:
1603 case 6:
1604 break;
1605 default:
1606 ret = -EINVAL;
1607 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608
1609 switch (sample_rate) {
1610 case 8000:
1611 case 11025:
1612 case 12000:
1613 case 16000:
1614 case 22050:
1615 case 24000:
1616 case 32000:
1617 case 44100:
1618 case 48000:
1619 break;
1620 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001621 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 }
1623
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001624 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625}
1626
1627static size_t get_input_buffer_size(uint32_t sample_rate,
1628 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001629 int channel_count,
1630 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631{
1632 size_t size = 0;
1633
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001634 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1635 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001637 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001638 if (is_low_latency)
1639 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001640 /* ToDo: should use frame_size computed based on the format and
1641 channel_count here. */
1642 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001644 /* make sure the size is multiple of 32 bytes
1645 * At 48 kHz mono 16-bit PCM:
1646 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1647 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1648 */
1649 size += 0x1f;
1650 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001651
1652 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653}
1654
1655static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1656{
1657 struct stream_out *out = (struct stream_out *)stream;
1658
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001659 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660}
1661
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001662static int out_set_sample_rate(struct audio_stream *stream __unused,
1663 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664{
1665 return -ENOSYS;
1666}
1667
1668static size_t out_get_buffer_size(const struct audio_stream *stream)
1669{
1670 struct stream_out *out = (struct stream_out *)stream;
1671
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001672 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001673 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001674 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1675 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001676
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001677 return out->config.period_size *
1678 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679}
1680
1681static uint32_t out_get_channels(const struct audio_stream *stream)
1682{
1683 struct stream_out *out = (struct stream_out *)stream;
1684
1685 return out->channel_mask;
1686}
1687
1688static audio_format_t out_get_format(const struct audio_stream *stream)
1689{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001690 struct stream_out *out = (struct stream_out *)stream;
1691
1692 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693}
1694
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001695static int out_set_format(struct audio_stream *stream __unused,
1696 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697{
1698 return -ENOSYS;
1699}
1700
1701static int out_standby(struct audio_stream *stream)
1702{
1703 struct stream_out *out = (struct stream_out *)stream;
1704 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001705
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301706 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1707 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001708 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1709 /* Ignore standby in case of voip call because the voip output
1710 * stream is closed in adev_close_output_stream()
1711 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301712 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001713 return 0;
1714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001716 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001718 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001720 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721 if (out->pcm) {
1722 pcm_close(out->pcm);
1723 out->pcm = NULL;
1724 }
1725 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001726 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001727 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001728 out->gapless_mdata.encoder_delay = 0;
1729 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730 if (out->compr != NULL) {
1731 compress_close(out->compr);
1732 out->compr = NULL;
1733 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001734 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001736 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 }
1738 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001739 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 return 0;
1741}
1742
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001743static int out_dump(const struct audio_stream *stream __unused,
1744 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745{
1746 return 0;
1747}
1748
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001749static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1750{
1751 int ret = 0;
1752 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001753 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001754 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001755 tmp_mdata.encoder_delay = 0;
1756 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001757 tmp_mdata.min_blk_size = 0;
1758 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001759
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001760 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001761 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001762 return -EINVAL;
1763 }
1764
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001765 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1766 if (ret >= 0) {
1767 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1768 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1769 ALOGV("ADTS format is set in offload mode");
1770 }
1771 out->send_new_metadata = 1;
1772 }
1773
Mingming Yin3ee55c62014-08-04 14:23:35 -07001774 if (out->format == AUDIO_FORMAT_FLAC) {
1775 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1776 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001777 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001778 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1779 out->send_new_metadata = 1;
1780 }
1781 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1782 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001783 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001784 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1785 out->send_new_metadata = 1;
1786 }
1787 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1788 if (ret >= 0) {
1789 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1790 out->send_new_metadata = 1;
1791 }
1792 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1793 if (ret >= 0) {
1794 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1795 out->send_new_metadata = 1;
1796 }
1797 }
1798
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001799 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1800 if(ret >= 0)
1801 is_meta_data_params = true;
1802 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1803 if(ret >= 0 )
1804 is_meta_data_params = true;
1805 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1806 if(ret >= 0 )
1807 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1809 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001810 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001812 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001813 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1814 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001815 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001816 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001817 }
1818
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001819 if(!is_meta_data_params) {
1820 ALOGV("%s: Not gapless meta data params", __func__);
1821 return 0;
1822 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 out->gapless_mdata = tmp_mdata;
1824 out->send_new_metadata = 1;
1825 ALOGV("%s new encoder delay %u and padding %u", __func__,
1826 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1827
1828 return 0;
1829}
1830
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001831static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1832{
1833 return out == adev->primary_output || out == adev->voice_tx_output;
1834}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1837{
1838 struct stream_out *out = (struct stream_out *)stream;
1839 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001840 struct audio_usecase *usecase;
1841 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842 struct str_parms *parms;
1843 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001844 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001845 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846
sangwoobc677242013-08-08 16:53:43 +09001847 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001848 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301850 if (!parms)
1851 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001852 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1853 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001856 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001858 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301859 * When HDMI cable is unplugged/usb hs is disconnected the
1860 * music playback is paused and the policy manager sends routing=0
1861 * But the audioflingercontinues to write data until standby time
1862 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001863 * Avoid this by routing audio to speaker until standby.
1864 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301865 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1866 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001868 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1869 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 }
1871
1872 /*
1873 * select_devices() call below switches all the usecases on the same
1874 * backend to the new device. Refer to check_usecases_codec_backend() in
1875 * the select_devices(). But how do we undo this?
1876 *
1877 * For example, music playback is active on headset (deep-buffer usecase)
1878 * and if we go to ringtones and select a ringtone, low-latency usecase
1879 * will be started on headset+speaker. As we can't enable headset+speaker
1880 * and headset devices at the same time, select_devices() switches the music
1881 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1882 * So when the ringtone playback is completed, how do we undo the same?
1883 *
1884 * We are relying on the out_set_parameters() call on deep-buffer output,
1885 * once the ringtone playback is ended.
1886 * NOTE: We should not check if the current devices are same as new devices.
1887 * Because select_devices() must be called to switch back the music
1888 * playback to headset.
1889 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001890 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 out->devices = val;
1892
1893 if (!out->standby)
1894 select_devices(adev, out->usecase);
1895
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001896 if (output_drives_call(adev, out)) {
1897 if(!voice_is_in_call(adev)) {
1898 if (adev->mode == AUDIO_MODE_IN_CALL) {
1899 adev->current_call_output = out;
1900 ret = voice_start_call(adev);
1901 }
1902 } else {
1903 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001904 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001905 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001906 }
1907 }
1908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001909 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001910 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001912
1913 if (out == adev->primary_output) {
1914 pthread_mutex_lock(&adev->lock);
1915 audio_extn_set_parameters(adev, parms);
1916 pthread_mutex_unlock(&adev->lock);
1917 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001918 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001919 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001920 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001921
1922 audio_extn_dts_create_state_notifier_node(out->usecase);
1923 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1924 popcount(out->channel_mask),
1925 out->playback_started);
1926
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001927 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001928 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301931error:
Eric Laurent994a6932013-07-17 11:51:42 -07001932 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 return ret;
1934}
1935
1936static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1937{
1938 struct stream_out *out = (struct stream_out *)stream;
1939 struct str_parms *query = str_parms_create_str(keys);
1940 char *str;
1941 char value[256];
1942 struct str_parms *reply = str_parms_create();
1943 size_t i, j;
1944 int ret;
1945 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001946
1947 if (!query || !reply) {
1948 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1949 return NULL;
1950 }
1951
Eric Laurent994a6932013-07-17 11:51:42 -07001952 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1954 if (ret >= 0) {
1955 value[0] = '\0';
1956 i = 0;
1957 while (out->supported_channel_masks[i] != 0) {
1958 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1959 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1960 if (!first) {
1961 strcat(value, "|");
1962 }
1963 strcat(value, out_channels_name_to_enum_table[j].name);
1964 first = false;
1965 break;
1966 }
1967 }
1968 i++;
1969 }
1970 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1971 str = str_parms_to_str(reply);
1972 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001973 voice_extn_out_get_parameters(out, query, reply);
1974 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001975 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001976 free(str);
1977 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001978 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001980
1981 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1982 if (ret >= 0) {
1983 value[0] = '\0';
1984 i = 0;
1985 first = true;
1986 while (out->supported_formats[i] != 0) {
1987 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1988 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1989 if (!first) {
1990 strcat(value, "|");
1991 }
1992 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1993 first = false;
1994 break;
1995 }
1996 }
1997 i++;
1998 }
1999 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2000 str = str_parms_to_str(reply);
2001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 str_parms_destroy(query);
2003 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002004 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 return str;
2006}
2007
2008static uint32_t out_get_latency(const struct audio_stream_out *stream)
2009{
2010 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002011 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012
Alexy Josephaa54c872014-12-03 02:46:47 -08002013 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002014 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002015 } else {
2016 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002017 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002018 }
2019
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302020 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002021 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022}
2023
2024static int out_set_volume(struct audio_stream_out *stream, float left,
2025 float right)
2026{
Eric Laurenta9024de2013-04-04 09:19:12 -07002027 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 int volume[2];
2029
Eric Laurenta9024de2013-04-04 09:19:12 -07002030 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2031 /* only take left channel into account: the API is for stereo anyway */
2032 out->muted = (left == 0.0f);
2033 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002034 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002035 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2036 /*
2037 * Set mute or umute on HDMI passthrough stream.
2038 * Only take left channel into account.
2039 * Mute is 0 and unmute 1
2040 */
2041 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2042 } else {
2043 char mixer_ctl_name[128];
2044 struct audio_device *adev = out->dev;
2045 struct mixer_ctl *ctl;
2046 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002047 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002049 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2050 "Compress Playback %d Volume", pcm_device_id);
2051 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2052 if (!ctl) {
2053 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2054 __func__, mixer_ctl_name);
2055 return -EINVAL;
2056 }
2057 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2058 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2059 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2060 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002062 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 return -ENOSYS;
2065}
2066
2067static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2068 size_t bytes)
2069{
2070 struct stream_out *out = (struct stream_out *)stream;
2071 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302072 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002073 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302076
Naresh Tanniru80659832014-06-04 18:17:56 +05302077 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002078 // increase written size during SSR to avoid mismatch
2079 // with the written frames count in AF
2080 if (!is_offload_usecase(out->usecase))
2081 out->written += bytes / (out->config.channels * sizeof(short));
2082
Naresh Tanniru80659832014-06-04 18:17:56 +05302083 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302084 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302085 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302086 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002087 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302088 //during SSR for compress usecase we should return error to flinger
2089 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2090 pthread_mutex_unlock(&out->lock);
2091 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302092 }
2093 }
2094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002096 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002097 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002098 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2099 ret = voice_extn_compress_voip_start_output_stream(out);
2100 else
2101 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002102 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002105 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 goto exit;
2107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002110 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002111 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002112 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002113 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002114 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2115 out->send_new_metadata = 0;
2116 }
2117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302119 if (ret < 0)
2120 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002121 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002122 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302123 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302125 } else if (-ENETRESET == ret) {
2126 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2127 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2128 pthread_mutex_unlock(&out->lock);
2129 out_standby(&out->stream.common);
2130 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302132 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 compress_start(out->compr);
2134 out->playback_started = 1;
2135 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002136
2137 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2138 popcount(out->channel_mask),
2139 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 }
2141 pthread_mutex_unlock(&out->lock);
2142 return ret;
2143 } else {
2144 if (out->pcm) {
2145 if (out->muted)
2146 memset((void *)buffer, 0, bytes);
2147 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002148 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2149 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2150 else
2151 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302152 if (ret < 0)
2153 ret = -errno;
2154 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002155 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 }
2158
2159exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302160 /* ToDo: There may be a corner case when SSR happens back to back during
2161 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302162 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302163 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302164 }
2165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 pthread_mutex_unlock(&out->lock);
2167
2168 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002169 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002170 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302171 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302172 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302173 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302174 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302175 out->standby = true;
2176 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002178 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302179 out_get_sample_rate(&out->stream.common));
2180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181 }
2182 return bytes;
2183}
2184
2185static int out_get_render_position(const struct audio_stream_out *stream,
2186 uint32_t *dsp_frames)
2187{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002188 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302189 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002190 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002191 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002192 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 pthread_mutex_lock(&out->lock);
2194 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302195 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302197 if (ret < 0)
2198 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 ALOGVV("%s rendered frames %d sample_rate %d",
2200 __func__, *dsp_frames, out->sample_rate);
2201 }
2202 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302203 if (-ENETRESET == ret) {
2204 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2205 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2206 return -EINVAL;
2207 } else if(ret < 0) {
2208 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2209 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302210 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2211 /*
2212 * Handle corner case where compress session is closed during SSR
2213 * and timestamp is queried
2214 */
2215 ALOGE(" ERROR: sound card not active, return error");
2216 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302217 } else {
2218 return 0;
2219 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002220 } else
2221 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222}
2223
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002224static int out_add_audio_effect(const struct audio_stream *stream __unused,
2225 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226{
2227 return 0;
2228}
2229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002230static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2231 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232{
2233 return 0;
2234}
2235
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002236static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2237 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238{
2239 return -EINVAL;
2240}
2241
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002242static int out_get_presentation_position(const struct audio_stream_out *stream,
2243 uint64_t *frames, struct timespec *timestamp)
2244{
2245 struct stream_out *out = (struct stream_out *)stream;
2246 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002247 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002248
2249 pthread_mutex_lock(&out->lock);
2250
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002251 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002252 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302253 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002254 &out->sample_rate);
2255 ALOGVV("%s rendered frames %ld sample_rate %d",
2256 __func__, dsp_frames, out->sample_rate);
2257 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302258 if (ret < 0)
2259 ret = -errno;
2260 if (-ENETRESET == ret) {
2261 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2262 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2263 ret = -EINVAL;
2264 } else
2265 ret = 0;
2266
Eric Laurent949a0892013-09-20 09:20:13 -07002267 /* this is the best we can do */
2268 clock_gettime(CLOCK_MONOTONIC, timestamp);
2269 }
2270 } else {
2271 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002272 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002273 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2274 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002275 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002276 // This adjustment accounts for buffering after app processor.
2277 // It is based on estimated DSP latency per use case, rather than exact.
2278 signed_frames -=
2279 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2280
Eric Laurent949a0892013-09-20 09:20:13 -07002281 // It would be unusual for this value to be negative, but check just in case ...
2282 if (signed_frames >= 0) {
2283 *frames = signed_frames;
2284 ret = 0;
2285 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002286 }
2287 }
2288 }
2289
2290 pthread_mutex_unlock(&out->lock);
2291
2292 return ret;
2293}
2294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002295static int out_set_callback(struct audio_stream_out *stream,
2296 stream_callback_t callback, void *cookie)
2297{
2298 struct stream_out *out = (struct stream_out *)stream;
2299
2300 ALOGV("%s", __func__);
2301 pthread_mutex_lock(&out->lock);
2302 out->offload_callback = callback;
2303 out->offload_cookie = cookie;
2304 pthread_mutex_unlock(&out->lock);
2305 return 0;
2306}
2307
2308static int out_pause(struct audio_stream_out* stream)
2309{
2310 struct stream_out *out = (struct stream_out *)stream;
2311 int status = -ENOSYS;
2312 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002313 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002314 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 pthread_mutex_lock(&out->lock);
2316 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302317 struct audio_device *adev = out->dev;
2318 int snd_scard_state = get_snd_card_state(adev);
2319
2320 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2321 status = compress_pause(out->compr);
2322
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002323 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002324
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302325 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002326 audio_extn_dts_notify_playback_state(out->usecase, 0,
2327 out->sample_rate, popcount(out->channel_mask),
2328 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 }
2330 pthread_mutex_unlock(&out->lock);
2331 }
2332 return status;
2333}
2334
2335static int out_resume(struct audio_stream_out* stream)
2336{
2337 struct stream_out *out = (struct stream_out *)stream;
2338 int status = -ENOSYS;
2339 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002340 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002341 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002342 status = 0;
2343 pthread_mutex_lock(&out->lock);
2344 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302345 struct audio_device *adev = out->dev;
2346 int snd_scard_state = get_snd_card_state(adev);
2347
2348 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2349 status = compress_resume(out->compr);
2350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002352
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302353 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002354 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2355 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 }
2357 pthread_mutex_unlock(&out->lock);
2358 }
2359 return status;
2360}
2361
2362static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2363{
2364 struct stream_out *out = (struct stream_out *)stream;
2365 int status = -ENOSYS;
2366 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002367 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 pthread_mutex_lock(&out->lock);
2369 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2370 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2371 else
2372 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2373 pthread_mutex_unlock(&out->lock);
2374 }
2375 return status;
2376}
2377
2378static int out_flush(struct audio_stream_out* stream)
2379{
2380 struct stream_out *out = (struct stream_out *)stream;
2381 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002382 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002383 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 pthread_mutex_lock(&out->lock);
2385 stop_compressed_output_l(out);
2386 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002387 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 return 0;
2389 }
2390 return -ENOSYS;
2391}
2392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393/** audio_stream_in implementation **/
2394static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2395{
2396 struct stream_in *in = (struct stream_in *)stream;
2397
2398 return in->config.rate;
2399}
2400
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002401static int in_set_sample_rate(struct audio_stream *stream __unused,
2402 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403{
2404 return -ENOSYS;
2405}
2406
2407static size_t in_get_buffer_size(const struct audio_stream *stream)
2408{
2409 struct stream_in *in = (struct stream_in *)stream;
2410
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002411 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2412 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002413 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2414 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002415
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002416 return in->config.period_size *
2417 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418}
2419
2420static uint32_t in_get_channels(const struct audio_stream *stream)
2421{
2422 struct stream_in *in = (struct stream_in *)stream;
2423
2424 return in->channel_mask;
2425}
2426
2427static audio_format_t in_get_format(const struct audio_stream *stream)
2428{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002429 struct stream_in *in = (struct stream_in *)stream;
2430
2431 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432}
2433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002434static int in_set_format(struct audio_stream *stream __unused,
2435 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436{
2437 return -ENOSYS;
2438}
2439
2440static int in_standby(struct audio_stream *stream)
2441{
2442 struct stream_in *in = (struct stream_in *)stream;
2443 struct audio_device *adev = in->dev;
2444 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302445 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2446 stream, in->usecase, use_case_table[in->usecase]);
2447
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002448 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2449 /* Ignore standby in case of voip call because the voip input
2450 * stream is closed in adev_close_input_stream()
2451 */
2452 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2453 return status;
2454 }
2455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002457 if (!in->standby && in->is_st_session) {
2458 ALOGD("%s: sound trigger pcm stop lab", __func__);
2459 audio_extn_sound_trigger_stop_lab(in);
2460 in->standby = 1;
2461 }
2462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002464 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002466 if (in->pcm) {
2467 pcm_close(in->pcm);
2468 in->pcm = NULL;
2469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002471 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 }
2473 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002474 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 return status;
2476}
2477
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002478static int in_dump(const struct audio_stream *stream __unused,
2479 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480{
2481 return 0;
2482}
2483
2484static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2485{
2486 struct stream_in *in = (struct stream_in *)stream;
2487 struct audio_device *adev = in->dev;
2488 struct str_parms *parms;
2489 char *str;
2490 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002491 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302493 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 parms = str_parms_create_str(kvpairs);
2495
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302496 if (!parms)
2497 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002499 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002500
2501 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2502 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 val = atoi(value);
2504 /* no audio source uses val == 0 */
2505 if ((in->source != val) && (val != 0)) {
2506 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002507 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2508 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2509 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2510 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002511 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002512 err = voice_extn_compress_voip_open_input_stream(in);
2513 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002514 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002515 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002516 }
2517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 }
2519 }
2520
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002521 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2522 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002524 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 in->device = val;
2526 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002527 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002528 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 }
2530 }
2531
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002532done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002534 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535
2536 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302537error:
Eric Laurent994a6932013-07-17 11:51:42 -07002538 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 return ret;
2540}
2541
2542static char* in_get_parameters(const struct audio_stream *stream,
2543 const char *keys)
2544{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002545 struct stream_in *in = (struct stream_in *)stream;
2546 struct str_parms *query = str_parms_create_str(keys);
2547 char *str;
2548 char value[256];
2549 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002550
2551 if (!query || !reply) {
2552 ALOGE("in_get_parameters: failed to create query or reply");
2553 return NULL;
2554 }
2555
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002556 ALOGV("%s: enter: keys - %s", __func__, keys);
2557
2558 voice_extn_in_get_parameters(in, query, reply);
2559
2560 str = str_parms_to_str(reply);
2561 str_parms_destroy(query);
2562 str_parms_destroy(reply);
2563
2564 ALOGV("%s: exit: returns - %s", __func__, str);
2565 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566}
2567
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002568static int in_set_gain(struct audio_stream_in *stream __unused,
2569 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570{
2571 return 0;
2572}
2573
2574static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2575 size_t bytes)
2576{
2577 struct stream_in *in = (struct stream_in *)stream;
2578 struct audio_device *adev = in->dev;
2579 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302580 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302583
2584 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302585 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302587 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302588 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002589 } else {
2590 if (in->is_st_session && !in->is_st_session_active) {
2591 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2592 ret= -EIO;;
2593 goto exit;
2594 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302595 }
2596 }
2597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002599 if (!in->is_st_session) {
2600 pthread_mutex_lock(&adev->lock);
2601 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2602 ret = voice_extn_compress_voip_start_input_stream(in);
2603 else
2604 ret = start_input_stream(in);
2605 pthread_mutex_unlock(&adev->lock);
2606 if (ret != 0) {
2607 goto exit;
2608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 }
2610 in->standby = 0;
2611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612
2613 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002614 if (audio_extn_ssr_get_enabled() &&
2615 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002616 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002617 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2618 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002619 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2620 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002621 else
2622 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302623 if (ret < 0)
2624 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 }
2626
2627 /*
2628 * Instead of writing zeroes here, we could trust the hardware
2629 * to always provide zeroes when muted.
2630 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302631 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2632 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 memset(buffer, 0, bytes);
2634
2635exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302636 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302637 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302638 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002639 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2640 session reading on LAB data. In this case do not set sound card state
2641 offline, instead mark this sound trigger session inactive to avoid
2642 further reading of LAB data from CPE driver. Marking the session
2643 inactive handles both CPE and ADSP SSR for sound trigger session */
2644 if (!in->is_st_session)
2645 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2646 else
2647 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 pthread_mutex_unlock(&in->lock);
2650
2651 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302652 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302653 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302654 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302655 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302656 in->standby = true;
2657 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302658 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002660 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002661 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302662 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 }
2664 return bytes;
2665}
2666
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002667static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668{
2669 return 0;
2670}
2671
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002672static int add_remove_audio_effect(const struct audio_stream *stream,
2673 effect_handle_t effect,
2674 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002676 struct stream_in *in = (struct stream_in *)stream;
2677 int status = 0;
2678 effect_descriptor_t desc;
2679
2680 status = (*effect)->get_descriptor(effect, &desc);
2681 if (status != 0)
2682 return status;
2683
2684 pthread_mutex_lock(&in->lock);
2685 pthread_mutex_lock(&in->dev->lock);
2686 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2687 in->enable_aec != enable &&
2688 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2689 in->enable_aec = enable;
2690 if (!in->standby)
2691 select_devices(in->dev, in->usecase);
2692 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002693 if (in->enable_ns != enable &&
2694 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2695 in->enable_ns = enable;
2696 if (!in->standby)
2697 select_devices(in->dev, in->usecase);
2698 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002699 pthread_mutex_unlock(&in->dev->lock);
2700 pthread_mutex_unlock(&in->lock);
2701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 return 0;
2703}
2704
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002705static int in_add_audio_effect(const struct audio_stream *stream,
2706 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707{
Eric Laurent994a6932013-07-17 11:51:42 -07002708 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002709 return add_remove_audio_effect(stream, effect, true);
2710}
2711
2712static int in_remove_audio_effect(const struct audio_stream *stream,
2713 effect_handle_t effect)
2714{
Eric Laurent994a6932013-07-17 11:51:42 -07002715 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002716 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717}
2718
2719static int adev_open_output_stream(struct audio_hw_device *dev,
2720 audio_io_handle_t handle,
2721 audio_devices_t devices,
2722 audio_output_flags_t flags,
2723 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002724 struct audio_stream_out **stream_out,
2725 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726{
2727 struct audio_device *adev = (struct audio_device *)dev;
2728 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002729 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002730 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302733
2734 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2735 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2736 ALOGE(" sound card is not active rejecting compress output open request");
2737 return -EINVAL;
2738 }
2739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2741
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302742 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2743 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2744 devices, flags, &out->stream);
2745
2746
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002747 if (!out) {
2748 return -ENOMEM;
2749 }
2750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 if (devices == AUDIO_DEVICE_NONE)
2752 devices = AUDIO_DEVICE_OUT_SPEAKER;
2753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 out->flags = flags;
2755 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002756 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002757 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758 out->sample_rate = config->sample_rate;
2759 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2760 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002761 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002762 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002763 out->non_blocking = 0;
2764 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765
2766 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002767 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2768 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2769 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2770
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002771 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002772 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2773 ret = read_hdmi_channel_masks(out);
2774
2775 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2776 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002777 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002778 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002779 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002780
2781 if (config->sample_rate == 0)
2782 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2783 if (config->channel_mask == 0)
2784 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2785
2786 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002787 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002788 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2789 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002791 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002793 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2794 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002795 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002796 ret = voice_extn_compress_voip_open_output_stream(out);
2797 if (ret != 0) {
2798 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2799 __func__, ret);
2800 goto error_open;
2801 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002802 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2803 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2804 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2805 ALOGE("%s: Unsupported Offload information", __func__);
2806 ret = -EINVAL;
2807 goto error_open;
2808 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002809
2810 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2811 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2812 ALOGV("read and update_pass through formats");
2813 ret = audio_extn_dolby_update_passt_formats(adev, out);
2814 if(ret != 0) {
2815 goto error_open;
2816 }
2817 if(config->offload_info.format == 0)
2818 config->offload_info.format = out->supported_formats[0];
2819 }
2820
Mingming Yin90310102013-11-13 16:57:00 -08002821 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002822 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823 ALOGE("%s: Unsupported audio format", __func__);
2824 ret = -EINVAL;
2825 goto error_open;
2826 }
2827
2828 out->compr_config.codec = (struct snd_codec *)
2829 calloc(1, sizeof(struct snd_codec));
2830
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002831 if (!out->compr_config.codec) {
2832 ret = -ENOMEM;
2833 goto error_open;
2834 }
2835
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002836 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837 if (config->offload_info.channel_mask)
2838 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002839 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002841 config->offload_info.channel_mask = config->channel_mask;
2842 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002843 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 out->sample_rate = config->offload_info.sample_rate;
2845
2846 out->stream.set_callback = out_set_callback;
2847 out->stream.pause = out_pause;
2848 out->stream.resume = out_resume;
2849 out->stream.drain = out_drain;
2850 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002851 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002853 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002854 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002855 audio_extn_dolby_get_snd_codec_id(adev, out,
2856 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002857 else
2858 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002860 if (audio_is_offload_pcm(config->offload_info.format)) {
2861 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002862 platform_get_pcm_offload_buffer_size(&config->offload_info);
2863 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2864 out->compr_config.fragment_size =
2865 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002866 } else {
2867 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002868 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002869 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2871 out->compr_config.codec->sample_rate =
2872 compress_get_alsa_rate(config->offload_info.sample_rate);
2873 out->compr_config.codec->bit_rate =
2874 config->offload_info.bit_rate;
2875 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002876 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002878 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002879 /*TODO: Do we need to change it for passthrough */
2880 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881
Mingming Yin3ee55c62014-08-04 14:23:35 -07002882 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2883 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002884 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2885 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002886 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002887 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2888
Mingming Yin3ee55c62014-08-04 14:23:35 -07002889 if (out->bit_width == 24) {
2890 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2891 }
2892
Amit Shekhar6f461b12014-08-01 14:52:58 -07002893 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002894 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002895
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2897 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002898
Alexy Josephaa54c872014-12-03 02:46:47 -08002899 if (config->offload_info.use_small_bufs) {
2900 //this flag is set from framework only if its for PCM formats
2901 //no need to check for PCM format again
2902 out->non_blocking = 0;
2903 out->use_small_bufs = true;
2904 ALOGI("Keep write blocking for small buff: non_blockling %d",
2905 out->non_blocking);
2906 }
2907
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002908 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002909 out->offload_state = OFFLOAD_STATE_IDLE;
2910 out->playback_started = 0;
2911
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002912 audio_extn_dts_create_state_notifier_node(out->usecase);
2913
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 create_offload_callback_thread(out);
2915 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2916 __func__, config->offload_info.version,
2917 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002918 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002919 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002920 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2921 ret = voice_check_and_set_incall_music_usecase(adev, out);
2922 if (ret != 0) {
2923 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2924 __func__, ret);
2925 goto error_open;
2926 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002927 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2928 if (config->sample_rate == 0)
2929 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2930 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2931 config->sample_rate != 8000) {
2932 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2933 ret = -EINVAL;
2934 goto error_open;
2935 }
2936 out->sample_rate = config->sample_rate;
2937 out->config.rate = config->sample_rate;
2938 if (config->format == AUDIO_FORMAT_DEFAULT)
2939 config->format = AUDIO_FORMAT_PCM_16_BIT;
2940 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2941 config->format = AUDIO_FORMAT_PCM_16_BIT;
2942 ret = -EINVAL;
2943 goto error_open;
2944 }
2945 out->format = config->format;
2946 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2947 out->config = pcm_config_afe_proxy_playback;
2948 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002949 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002950 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2952 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002954 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2955 format = AUDIO_FORMAT_PCM_16_BIT;
2956 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2957 out->config = pcm_config_deep_buffer;
2958 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002959 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002960 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002961 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002962 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002963 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002964 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 }
2966
Amit Shekhar1d896042014-10-03 13:16:09 -07002967 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2968 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002969 /* TODO remove this hardcoding and check why width is zero*/
2970 if (out->bit_width == 0)
2971 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002972 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2973 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002974 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002975 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002976 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2977 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2978 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002979 if(adev->primary_output == NULL)
2980 adev->primary_output = out;
2981 else {
2982 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002983 ret = -EEXIST;
2984 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002985 }
2986 }
2987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 /* Check if this usecase is already existing */
2989 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002990 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2991 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002994 ret = -EEXIST;
2995 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 }
2997 pthread_mutex_unlock(&adev->lock);
2998
2999 out->stream.common.get_sample_rate = out_get_sample_rate;
3000 out->stream.common.set_sample_rate = out_set_sample_rate;
3001 out->stream.common.get_buffer_size = out_get_buffer_size;
3002 out->stream.common.get_channels = out_get_channels;
3003 out->stream.common.get_format = out_get_format;
3004 out->stream.common.set_format = out_set_format;
3005 out->stream.common.standby = out_standby;
3006 out->stream.common.dump = out_dump;
3007 out->stream.common.set_parameters = out_set_parameters;
3008 out->stream.common.get_parameters = out_get_parameters;
3009 out->stream.common.add_audio_effect = out_add_audio_effect;
3010 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3011 out->stream.get_latency = out_get_latency;
3012 out->stream.set_volume = out_set_volume;
3013 out->stream.write = out_write;
3014 out->stream.get_render_position = out_get_render_position;
3015 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003016 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003019 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003020 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003022 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3023 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 config->format = out->stream.common.get_format(&out->stream.common);
3026 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3027 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3028
3029 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303030 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3031 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003032
3033 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3034 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3035 popcount(out->channel_mask), out->playback_started);
3036
Eric Laurent994a6932013-07-17 11:51:42 -07003037 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003039
3040error_open:
3041 free(out);
3042 *stream_out = NULL;
3043 ALOGD("%s: exit: ret %d", __func__, ret);
3044 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045}
3046
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003047static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 struct audio_stream_out *stream)
3049{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 struct stream_out *out = (struct stream_out *)stream;
3051 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003052 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303054 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3055
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003056 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303057 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003058 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303059 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003060 if(ret != 0)
3061 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3062 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003063 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003064 out_standby(&stream->common);
3065
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003066 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003067 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003069 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 if (out->compr_config.codec != NULL)
3071 free(out->compr_config.codec);
3072 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003073
3074 if (adev->voice_tx_output == out)
3075 adev->voice_tx_output = NULL;
3076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 pthread_cond_destroy(&out->cond);
3078 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003080 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081}
3082
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003083static void close_compress_sessions(struct audio_device *adev)
3084{
Mingming Yin7b762e72015-03-04 13:47:32 -08003085 struct stream_out *out;
3086 struct listnode *node;
3087 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003088 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003089 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003090 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003091 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003092 if (usecase && usecase->stream.out) {
3093 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3094 out = usecase->stream.out;
3095 pthread_mutex_unlock(&adev->lock);
3096 out_standby(&out->stream.common);
3097 pthread_mutex_lock(&adev->lock);
3098 }
3099 }
3100 }
3101 pthread_mutex_unlock(&adev->lock);
3102}
3103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3105{
3106 struct audio_device *adev = (struct audio_device *)dev;
3107 struct str_parms *parms;
3108 char *str;
3109 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003110 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003111 int ret;
3112 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003114 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303117 if (!parms)
3118 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003119 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3120 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303121 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303122 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303123 struct listnode *node;
3124 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303125 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303126 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003127 //close compress sessions on OFFLINE status
3128 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303129 } else if (strstr(snd_card_status, "ONLINE")) {
3130 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303131 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303133 }
3134
3135 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003136 status = voice_set_parameters(adev, parms);
3137 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003138 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003140 status = platform_set_parameters(adev->platform, parms);
3141 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003142 goto done;
3143
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003144 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3145 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003146 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3148 adev->bluetooth_nrec = true;
3149 else
3150 adev->bluetooth_nrec = false;
3151 }
3152
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003153 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3154 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3156 adev->screen_off = false;
3157 else
3158 adev->screen_off = true;
3159 }
3160
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003161 ret = str_parms_get_int(parms, "rotation", &val);
3162 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003163 bool reverse_speakers = false;
3164 switch(val) {
3165 // FIXME: note that the code below assumes that the speakers are in the correct placement
3166 // relative to the user when the device is rotated 90deg from its default rotation. This
3167 // assumption is device-specific, not platform-specific like this code.
3168 case 270:
3169 reverse_speakers = true;
3170 break;
3171 case 0:
3172 case 90:
3173 case 180:
3174 break;
3175 default:
3176 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003177 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003178 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 if (status == 0) {
3180 if (adev->speaker_lr_swap != reverse_speakers) {
3181 adev->speaker_lr_swap = reverse_speakers;
3182 // only update the selected device if there is active pcm playback
3183 struct audio_usecase *usecase;
3184 struct listnode *node;
3185 list_for_each(node, &adev->usecase_list) {
3186 usecase = node_to_item(node, struct audio_usecase, list);
3187 if (usecase->type == PCM_PLAYBACK) {
3188 select_devices(adev, usecase->id);
3189 break;
3190 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003191 }
3192 }
3193 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003194 }
3195
Mingming Yin514a8bc2014-07-29 15:22:21 -07003196 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3197 if (ret >= 0) {
3198 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3199 adev->bt_wb_speech_enabled = true;
3200 else
3201 adev->bt_wb_speech_enabled = false;
3202 }
3203
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003204 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3205 if (ret >= 0) {
3206 val = atoi(value);
3207 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3208 ALOGV("cache new edid");
3209 platform_cache_edid(adev->platform);
3210 }
3211 }
3212
3213 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3214 if (ret >= 0) {
3215 val = atoi(value);
3216 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3217 ALOGV("invalidate cached edid");
3218 platform_invalidate_edid(adev->platform);
3219 }
3220 }
3221
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003222 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003223
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003224done:
3225 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003226 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303227error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003228 ALOGV("%s: exit with code(%d)", __func__, status);
3229 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230}
3231
3232static char* adev_get_parameters(const struct audio_hw_device *dev,
3233 const char *keys)
3234{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003235 struct audio_device *adev = (struct audio_device *)dev;
3236 struct str_parms *reply = str_parms_create();
3237 struct str_parms *query = str_parms_create_str(keys);
3238 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303239 char value[256] = {0};
3240 int ret = 0;
3241
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003242 if (!query || !reply) {
3243 ALOGE("adev_get_parameters: failed to create query or reply");
3244 return NULL;
3245 }
3246
Naresh Tannirud7205b62014-06-20 02:54:48 +05303247 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3248 sizeof(value));
3249 if (ret >=0) {
3250 int val = 1;
3251 pthread_mutex_lock(&adev->snd_card_status.lock);
3252 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3253 val = 0;
3254 pthread_mutex_unlock(&adev->snd_card_status.lock);
3255 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3256 goto exit;
3257 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003258
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003259 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003260 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003261 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003262 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303263 pthread_mutex_unlock(&adev->lock);
3264
Naresh Tannirud7205b62014-06-20 02:54:48 +05303265exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003266 str = str_parms_to_str(reply);
3267 str_parms_destroy(query);
3268 str_parms_destroy(reply);
3269
3270 ALOGV("%s: exit: returns - %s", __func__, str);
3271 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272}
3273
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003274static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275{
3276 return 0;
3277}
3278
3279static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3280{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003281 int ret;
3282 struct audio_device *adev = (struct audio_device *)dev;
3283 pthread_mutex_lock(&adev->lock);
3284 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003285 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003286 pthread_mutex_unlock(&adev->lock);
3287 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288}
3289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003290static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3291 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292{
3293 return -ENOSYS;
3294}
3295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003296static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3297 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298{
3299 return -ENOSYS;
3300}
3301
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003302static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3303 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304{
3305 return -ENOSYS;
3306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3309 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return -ENOSYS;
3312}
3313
3314static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3315{
3316 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 pthread_mutex_lock(&adev->lock);
3319 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003322 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3323 voice_is_in_call(adev)) {
3324 voice_stop_call(adev);
3325 adev->current_call_output = NULL;
3326 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 }
3328 pthread_mutex_unlock(&adev->lock);
3329 return 0;
3330}
3331
3332static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3333{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003334 int ret;
3335
3336 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003337 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003338 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3339 pthread_mutex_unlock(&adev->lock);
3340
3341 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342}
3343
3344static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3345{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003346 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 return 0;
3348}
3349
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003350static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351 const struct audio_config *config)
3352{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003353 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003355 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3356 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357}
3358
3359static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003360 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361 audio_devices_t devices,
3362 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003363 struct audio_stream_in **stream_in,
3364 audio_input_flags_t flags __unused,
3365 const char *address __unused,
3366 audio_source_t source __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367{
3368 struct audio_device *adev = (struct audio_device *)dev;
3369 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003370 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003371 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003372 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 *stream_in = NULL;
3375 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3376 return -EINVAL;
3377
3378 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003379
3380 if (!in) {
3381 ALOGE("failed to allocate input stream");
3382 return -ENOMEM;
3383 }
3384
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303385 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003386 stream_handle(%p) io_handle(%d)",__func__, config->sample_rate, config->channel_mask,
3387 devices, &in->stream, handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003389 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 in->stream.common.get_sample_rate = in_get_sample_rate;
3392 in->stream.common.set_sample_rate = in_set_sample_rate;
3393 in->stream.common.get_buffer_size = in_get_buffer_size;
3394 in->stream.common.get_channels = in_get_channels;
3395 in->stream.common.get_format = in_get_format;
3396 in->stream.common.set_format = in_set_format;
3397 in->stream.common.standby = in_standby;
3398 in->stream.common.dump = in_dump;
3399 in->stream.common.set_parameters = in_set_parameters;
3400 in->stream.common.get_parameters = in_get_parameters;
3401 in->stream.common.add_audio_effect = in_add_audio_effect;
3402 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3403 in->stream.set_gain = in_set_gain;
3404 in->stream.read = in_read;
3405 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3406
3407 in->device = devices;
3408 in->source = AUDIO_SOURCE_DEFAULT;
3409 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 in->standby = 1;
3411 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003412 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413
3414 /* Update config params with the requested sample rate and channels */
3415 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003416 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3417 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3418 is_low_latency = true;
3419#if LOW_LATENCY_CAPTURE_USE_CASE
3420 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3421#endif
3422 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003425 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003427 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303428 if (adev->mode != AUDIO_MODE_IN_CALL) {
3429 ret = -EINVAL;
3430 goto err_open;
3431 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003432 if (config->sample_rate == 0)
3433 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3434 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3435 config->sample_rate != 8000) {
3436 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3437 ret = -EINVAL;
3438 goto err_open;
3439 }
3440 if (config->format == AUDIO_FORMAT_DEFAULT)
3441 config->format = AUDIO_FORMAT_PCM_16_BIT;
3442 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3443 config->format = AUDIO_FORMAT_PCM_16_BIT;
3444 ret = -EINVAL;
3445 goto err_open;
3446 }
3447
3448 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3449 in->config = pcm_config_afe_proxy_record;
3450 in->config.channels = channel_count;
3451 in->config.rate = config->sample_rate;
3452 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003453 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003454 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003455 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3456 ret = -EINVAL;
3457 goto err_open;
3458 }
3459 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003460 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003461 }
Mingming Yine62d7842013-10-25 16:26:03 -07003462 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003463 audio_extn_compr_cap_format_supported(config->format) &&
3464 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003465 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003466 } else {
3467 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003468 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003469 buffer_size = get_input_buffer_size(config->sample_rate,
3470 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003471 channel_count,
3472 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003473 in->config.period_size = buffer_size / frame_size;
3474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003476 /* This stream could be for sound trigger lab,
3477 get sound trigger pcm if present */
3478 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303479 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003482 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003483 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484
3485err_open:
3486 free(in);
3487 *stream_in = NULL;
3488 return ret;
3489}
3490
3491static void adev_close_input_stream(struct audio_hw_device *dev,
3492 struct audio_stream_in *stream)
3493{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003494 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003495 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003496 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303497
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303498 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003499
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303500 /* Disable echo reference while closing input stream */
3501 platform_set_echo_reference(adev->platform, false);
3502
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003503 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303504 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003505 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303506 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003507 if (ret != 0)
3508 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3509 __func__, ret);
3510 } else
3511 in_standby(&stream->common);
3512
Mingming Yin7b762e72015-03-04 13:47:32 -08003513 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003514 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003515 audio_extn_ssr_deinit();
3516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517
Mingming Yine62d7842013-10-25 16:26:03 -07003518 if(audio_extn_compr_cap_enabled() &&
3519 audio_extn_compr_cap_format_supported(in->config.format))
3520 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003521
3522 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 return;
3524}
3525
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003526static int adev_dump(const audio_hw_device_t *device __unused,
3527 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528{
3529 return 0;
3530}
3531
3532static int adev_close(hw_device_t *device)
3533{
3534 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003535
3536 if (!adev)
3537 return 0;
3538
3539 pthread_mutex_lock(&adev_init_lock);
3540
3541 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003542 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003543 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003544 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003545 audio_route_free(adev->audio_route);
3546 free(adev->snd_dev_ref_cnt);
3547 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003548 free(device);
3549 adev = NULL;
3550 }
3551 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 return 0;
3553}
3554
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003555/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3556 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3557 * just that it _might_ work.
3558 */
3559static int period_size_is_plausible_for_low_latency(int period_size)
3560{
3561 switch (period_size) {
3562 case 160:
3563 case 240:
3564 case 320:
3565 case 480:
3566 return 1;
3567 default:
3568 return 0;
3569 }
3570}
3571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572static int adev_open(const hw_module_t *module, const char *name,
3573 hw_device_t **device)
3574{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003575 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003577 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3579
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003580 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003581 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003582 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003583 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003584 ALOGD("%s: returning existing instance of adev", __func__);
3585 ALOGD("%s: exit", __func__);
3586 pthread_mutex_unlock(&adev_init_lock);
3587 return 0;
3588 }
3589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 adev = calloc(1, sizeof(struct audio_device));
3591
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003592 if (!adev) {
3593 pthread_mutex_unlock(&adev_init_lock);
3594 return -ENOMEM;
3595 }
3596
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003597 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3600 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3601 adev->device.common.module = (struct hw_module_t *)module;
3602 adev->device.common.close = adev_close;
3603
3604 adev->device.init_check = adev_init_check;
3605 adev->device.set_voice_volume = adev_set_voice_volume;
3606 adev->device.set_master_volume = adev_set_master_volume;
3607 adev->device.get_master_volume = adev_get_master_volume;
3608 adev->device.set_master_mute = adev_set_master_mute;
3609 adev->device.get_master_mute = adev_get_master_mute;
3610 adev->device.set_mode = adev_set_mode;
3611 adev->device.set_mic_mute = adev_set_mic_mute;
3612 adev->device.get_mic_mute = adev_get_mic_mute;
3613 adev->device.set_parameters = adev_set_parameters;
3614 adev->device.get_parameters = adev_get_parameters;
3615 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3616 adev->device.open_output_stream = adev_open_output_stream;
3617 adev->device.close_output_stream = adev_close_output_stream;
3618 adev->device.open_input_stream = adev_open_input_stream;
3619 adev->device.close_input_stream = adev_close_input_stream;
3620 adev->device.dump = adev_dump;
3621
3622 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003624 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003625 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003628 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003629 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003630 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3631 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003632 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003633 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003634 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003635 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003636 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303637
3638 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3639 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003641 adev->platform = platform_init(adev);
3642 if (!adev->platform) {
3643 free(adev->snd_dev_ref_cnt);
3644 free(adev);
3645 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3646 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003647 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003648 return -EINVAL;
3649 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003650
Naresh Tanniru4c630392014-05-12 01:05:52 +05303651 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3652
Eric Laurentc4aef752013-09-12 17:45:53 -07003653 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3654 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3655 if (adev->visualizer_lib == NULL) {
3656 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3657 } else {
3658 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3659 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003660 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003661 "visualizer_hal_start_output");
3662 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003663 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003664 "visualizer_hal_stop_output");
3665 }
3666 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003667 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003668 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003669
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003670 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3671 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3672 if (adev->offload_effects_lib == NULL) {
3673 ALOGE("%s: DLOPEN failed for %s", __func__,
3674 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3675 } else {
3676 ALOGV("%s: DLOPEN successful for %s", __func__,
3677 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3678 adev->offload_effects_start_output =
3679 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3680 "offload_effects_bundle_hal_start_output");
3681 adev->offload_effects_stop_output =
3682 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3683 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003684 adev->offload_effects_set_hpx_state =
3685 (int (*)(bool))dlsym(adev->offload_effects_lib,
3686 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003687 }
3688 }
3689
Mingming Yin514a8bc2014-07-29 15:22:21 -07003690 adev->bt_wb_speech_enabled = false;
3691
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003692 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 *device = &adev->device.common;
3694
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003695 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3696 &adev->streams_output_cfg_list);
3697
Kiran Kandi910e1862013-10-29 13:29:42 -07003698 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003699
3700 char value[PROPERTY_VALUE_MAX];
3701 int trial;
3702 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3703 trial = atoi(value);
3704 if (period_size_is_plausible_for_low_latency(trial)) {
3705 pcm_config_low_latency.period_size = trial;
3706 pcm_config_low_latency.start_threshold = trial / 4;
3707 pcm_config_low_latency.avail_min = trial / 4;
3708 configured_low_latency_capture_period_size = trial;
3709 }
3710 }
3711 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3712 trial = atoi(value);
3713 if (period_size_is_plausible_for_low_latency(trial)) {
3714 configured_low_latency_capture_period_size = trial;
3715 }
3716 }
3717
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003718 pthread_mutex_unlock(&adev_init_lock);
3719
Eric Laurent994a6932013-07-17 11:51:42 -07003720 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 return 0;
3722}
3723
3724static struct hw_module_methods_t hal_module_methods = {
3725 .open = adev_open,
3726};
3727
3728struct audio_module HAL_MODULE_INFO_SYM = {
3729 .common = {
3730 .tag = HARDWARE_MODULE_TAG,
3731 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3732 .hal_api_version = HARDWARE_HAL_API_VERSION,
3733 .id = AUDIO_HARDWARE_MODULE_ID,
3734 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003735 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 .methods = &hal_module_methods,
3737 },
3738};