blob: 567977033f263a83537b74b066bdba5ef5ab4e5d [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 &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530663 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700664 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700665 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
666 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700667 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700668 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700669 switch_device[usecase->id] = true;
670 num_uc_to_switch++;
671 }
672 }
673
674 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700675 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700676
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530677 /* Make sure the previous devices to be disabled first and then enable the
678 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700679 list_for_each(node, &adev->usecase_list) {
680 usecase = node_to_item(node, struct audio_usecase, list);
681 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700682 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800683 }
684 }
685
686 list_for_each(node, &adev->usecase_list) {
687 usecase = node_to_item(node, struct audio_usecase, list);
688 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700689 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700690 }
691 }
692
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693 /* Re-route all the usecases on the shared backend other than the
694 specified usecase to new snd devices */
695 list_for_each(node, &adev->usecase_list) {
696 usecase = node_to_item(node, struct audio_usecase, list);
697 /* Update the in_snd_device only before enabling the audio route */
698 if (switch_device[usecase->id] ) {
699 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800700 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530701 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700702 }
703 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 }
705}
706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700708static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700710 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700711 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712
713 switch (channels) {
714 /*
715 * Do not handle stereo output in Multi-channel cases
716 * Stereo case is handled in normal playback path
717 */
718 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700719 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
720 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
721 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
722 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
723 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
724 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725 break;
726 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700727 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
728 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
729 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
730 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
731 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
732 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
733 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800734 break;
735 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700736 ALOGE("HDMI does not support multi channel playback");
737 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800738 break;
739 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700740 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741}
742
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700743static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
744{
745 struct audio_usecase *usecase;
746 struct listnode *node;
747
748 list_for_each(node, &adev->usecase_list) {
749 usecase = node_to_item(node, struct audio_usecase, list);
750 if (usecase->type == VOICE_CALL) {
751 ALOGV("%s: usecase id %d", __func__, usecase->id);
752 return usecase->id;
753 }
754 }
755 return USECASE_INVALID;
756}
757
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700758struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700759 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760{
761 struct audio_usecase *usecase;
762 struct listnode *node;
763
764 list_for_each(node, &adev->usecase_list) {
765 usecase = node_to_item(node, struct audio_usecase, list);
766 if (usecase->id == uc_id)
767 return usecase;
768 }
769 return NULL;
770}
771
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700772int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800774 snd_device_t out_snd_device = SND_DEVICE_NONE;
775 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700776 struct audio_usecase *usecase = NULL;
777 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800778 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800779 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800780 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800781 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700782 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784 usecase = get_usecase_from_list(adev, uc_id);
785 if (usecase == NULL) {
786 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
787 return -EINVAL;
788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800789
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800790 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800791 (usecase->type == VOIP_CALL) ||
792 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700793 out_snd_device = platform_get_output_snd_device(adev->platform,
794 usecase->stream.out->devices);
795 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700796 usecase->devices = usecase->stream.out->devices;
797 } else {
798 /*
799 * If the voice call is active, use the sound devices of voice call usecase
800 * so that it would not result any device switch. All the usecases will
801 * be switched to new device when select_devices() is called for voice call
802 * usecase. This is to avoid switching devices for voice call when
803 * check_usecases_codec_backend() is called below.
804 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700805 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700806 vc_usecase = get_usecase_from_list(adev,
807 get_voice_usecase_id_from_list(adev));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700808 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
809 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700810 in_snd_device = vc_usecase->in_snd_device;
811 out_snd_device = vc_usecase->out_snd_device;
812 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800813 } else if (voice_extn_compress_voip_is_active(adev)) {
814 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700815 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530816 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700817 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800818 in_snd_device = voip_usecase->in_snd_device;
819 out_snd_device = voip_usecase->out_snd_device;
820 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800821 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800822 hfp_ucid = audio_extn_hfp_get_usecase();
823 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700824 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800825 in_snd_device = hfp_usecase->in_snd_device;
826 out_snd_device = hfp_usecase->out_snd_device;
827 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 }
829 if (usecase->type == PCM_PLAYBACK) {
830 usecase->devices = usecase->stream.out->devices;
831 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700832 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700833 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700835 if (usecase->stream.out == adev->primary_output &&
836 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800837 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
838 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700839 select_devices(adev, adev->active_input->usecase);
840 }
841 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842 } else if (usecase->type == PCM_CAPTURE) {
843 usecase->devices = usecase->stream.in->device;
844 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700845 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700846 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530847 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
848 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
849 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
850 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700851 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800852 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700853 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
854 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700855 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700856 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700857 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858 }
859 }
860
861 if (out_snd_device == usecase->out_snd_device &&
862 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800863 return 0;
864 }
865
sangwoobc677242013-08-08 16:53:43 +0900866 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700867 out_snd_device, platform_get_snd_device_name(out_snd_device),
868 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800870 /*
871 * Limitation: While in call, to do a device switch we need to disable
872 * and enable both RX and TX devices though one of them is same as current
873 * device.
874 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700875 if ((usecase->type == VOICE_CALL) &&
876 (usecase->in_snd_device != SND_DEVICE_NONE) &&
877 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700878 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800879 }
880
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 /* Disable current sound devices */
882 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700883 disable_audio_route(adev, usecase);
884 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800885 }
886
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700888 disable_audio_route(adev, usecase);
889 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800890 }
891
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800892 /* Applicable only on the targets that has external modem.
893 * New device information should be sent to modem before enabling
894 * the devices to reduce in-call device switch time.
895 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700896 if ((usecase->type == VOICE_CALL) &&
897 (usecase->in_snd_device != SND_DEVICE_NONE) &&
898 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800899 status = platform_switch_voice_call_enable_device_config(adev->platform,
900 out_snd_device,
901 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700902 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800903
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 /* Enable new sound devices */
905 if (out_snd_device != SND_DEVICE_NONE) {
906 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
907 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700908 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800909 }
910
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700911 if (in_snd_device != SND_DEVICE_NONE) {
912 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700913 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700914 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915
Avinash Vaish71a8b972014-07-24 15:36:33 +0530916 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700917 status = platform_switch_voice_call_device_post(adev->platform,
918 out_snd_device,
919 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530920 enable_audio_route_for_voice_usecases(adev, usecase);
921 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800922
sangwoo170731f2013-06-08 15:36:36 +0900923 usecase->in_snd_device = in_snd_device;
924 usecase->out_snd_device = out_snd_device;
925
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530926 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700927 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530928 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700929 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530930 usecase->stream.out->flags,
931 usecase->stream.out->format,
932 usecase->stream.out->sample_rate,
933 usecase->stream.out->bit_width,
934 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700935 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530936 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700937
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700938 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900939
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800940 /* Applicable only on the targets that has external modem.
941 * Enable device command should be sent to modem only after
942 * enabling voice call mixer controls
943 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700944 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800945 status = platform_switch_voice_call_usecase_route_post(adev->platform,
946 out_snd_device,
947 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530948 ALOGD("%s: done",__func__);
949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800950 return status;
951}
952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953static int stop_input_stream(struct stream_in *in)
954{
955 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956 struct audio_usecase *uc_info;
957 struct audio_device *adev = in->dev;
958
Eric Laurentc8400632013-02-14 19:04:54 -0800959 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800960
Eric Laurent994a6932013-07-17 11:51:42 -0700961 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 uc_info = get_usecase_from_list(adev, in->usecase);
964 if (uc_info == NULL) {
965 ALOGE("%s: Could not find the usecase (%d) in the list",
966 __func__, in->usecase);
967 return -EINVAL;
968 }
969
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800970 /* Close in-call recording streams */
971 voice_check_and_stop_incall_rec_usecase(adev, in);
972
Eric Laurent150dbfe2013-02-27 14:31:02 -0800973 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700974 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975
976 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700977 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800979 list_remove(&uc_info->list);
980 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981
Eric Laurent994a6932013-07-17 11:51:42 -0700982 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983 return ret;
984}
985
986int start_input_stream(struct stream_in *in)
987{
988 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800989 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 struct audio_usecase *uc_info;
991 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530992 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993
Mingming Yine62d7842013-10-25 16:26:03 -0700994 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530995 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
996 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700997
Naresh Tanniru80659832014-06-04 18:17:56 +0530998
999 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301000 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301001 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301002 goto error_config;
1003 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301004
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001005 /* Check if source matches incall recording usecase criteria */
1006 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1007 if (ret)
1008 goto error_config;
1009 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001010 ALOGD("%s: Updated usecase(%d: %s)",
1011 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001012
Eric Laurentb23d5282013-05-14 15:27:20 -07001013 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001014 if (in->pcm_device_id < 0) {
1015 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1016 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001017 ret = -EINVAL;
1018 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020
1021 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001023
1024 if (!uc_info) {
1025 ret = -ENOMEM;
1026 goto error_config;
1027 }
1028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 uc_info->id = in->usecase;
1030 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001031 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032 uc_info->devices = in->device;
1033 uc_info->in_snd_device = SND_DEVICE_NONE;
1034 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001036 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301037 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039
Eric Laurentc8400632013-02-14 19:04:54 -08001040 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001041 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1042
1043 unsigned int flags = PCM_IN;
1044 unsigned int pcm_open_retry_count = 0;
1045
1046 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1047 flags |= PCM_MMAP | PCM_NOIRQ;
1048 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1049 }
1050
1051 while (1) {
1052 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1053 flags, &in->config);
1054 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1055 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1056 if (in->pcm != NULL) {
1057 pcm_close(in->pcm);
1058 in->pcm = NULL;
1059 }
1060 if (pcm_open_retry_count-- == 0) {
1061 ret = -EIO;
1062 goto error_open;
1063 }
1064 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1065 continue;
1066 }
1067 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301069 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301070
Eric Laurent994a6932013-07-17 11:51:42 -07001071 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001072 return ret;
1073
1074error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301076 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001077
1078error_config:
1079 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001081
1082 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083}
1084
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001085/* must be called with out->lock locked */
1086static int send_offload_cmd_l(struct stream_out* out, int command)
1087{
1088 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1089
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001090 if (!cmd) {
1091 ALOGE("failed to allocate mem for command 0x%x", command);
1092 return -ENOMEM;
1093 }
1094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001095 ALOGVV("%s %d", __func__, command);
1096
1097 cmd->cmd = command;
1098 list_add_tail(&out->offload_cmd_list, &cmd->node);
1099 pthread_cond_signal(&out->offload_cond);
1100 return 0;
1101}
1102
1103/* must be called iwth out->lock locked */
1104static void stop_compressed_output_l(struct stream_out *out)
1105{
1106 out->offload_state = OFFLOAD_STATE_IDLE;
1107 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001108 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001109 if (out->compr != NULL) {
1110 compress_stop(out->compr);
1111 while (out->offload_thread_blocked) {
1112 pthread_cond_wait(&out->cond, &out->lock);
1113 }
1114 }
1115}
1116
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001117bool is_offload_usecase(audio_usecase_t uc_id)
1118{
1119 unsigned int i;
1120 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1121 if (uc_id == offload_usecases[i])
1122 return true;
1123 }
1124 return false;
1125}
1126
1127static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1128{
1129 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1130 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1131 char value[PROPERTY_VALUE_MAX] = {0};
1132
1133 property_get("audio.offload.multiple.enabled", value, NULL);
1134 if (!(atoi(value) || !strncmp("true", value, 4)))
1135 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1136
1137 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1138 for (i = 0; i < num_usecase; i++) {
1139 if (!(adev->offload_usecases_state & (0x1<<i))) {
1140 adev->offload_usecases_state |= 0x1 << i;
1141 ret = offload_usecases[i];
1142 break;
1143 }
1144 }
1145 ALOGV("%s: offload usecase is %d", __func__, ret);
1146 return ret;
1147}
1148
1149static void free_offload_usecase(struct audio_device *adev,
1150 audio_usecase_t uc_id)
1151{
1152 unsigned int i;
1153 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1154 if (offload_usecases[i] == uc_id) {
1155 adev->offload_usecases_state &= ~(0x1<<i);
1156 break;
1157 }
1158 }
1159 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1160}
1161
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001162static void *offload_thread_loop(void *context)
1163{
1164 struct stream_out *out = (struct stream_out *) context;
1165 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001166 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001167
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001168 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1169 set_sched_policy(0, SP_FOREGROUND);
1170 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1171
1172 ALOGV("%s", __func__);
1173 pthread_mutex_lock(&out->lock);
1174 for (;;) {
1175 struct offload_cmd *cmd = NULL;
1176 stream_callback_event_t event;
1177 bool send_callback = false;
1178
1179 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1180 __func__, list_empty(&out->offload_cmd_list),
1181 out->offload_state);
1182 if (list_empty(&out->offload_cmd_list)) {
1183 ALOGV("%s SLEEPING", __func__);
1184 pthread_cond_wait(&out->offload_cond, &out->lock);
1185 ALOGV("%s RUNNING", __func__);
1186 continue;
1187 }
1188
1189 item = list_head(&out->offload_cmd_list);
1190 cmd = node_to_item(item, struct offload_cmd, node);
1191 list_remove(item);
1192
1193 ALOGVV("%s STATE %d CMD %d out->compr %p",
1194 __func__, out->offload_state, cmd->cmd, out->compr);
1195
1196 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1197 free(cmd);
1198 break;
1199 }
1200
1201 if (out->compr == NULL) {
1202 ALOGE("%s: Compress handle is NULL", __func__);
1203 pthread_cond_signal(&out->cond);
1204 continue;
1205 }
1206 out->offload_thread_blocked = true;
1207 pthread_mutex_unlock(&out->lock);
1208 send_callback = false;
1209 switch(cmd->cmd) {
1210 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001211 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001212 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001213 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001214 send_callback = true;
1215 event = STREAM_CBK_EVENT_WRITE_READY;
1216 break;
1217 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001218 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301219 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001220 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301221 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001222 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301223 if (ret < 0)
1224 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301225 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301226 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001227 compress_drain(out->compr);
1228 else
1229 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301230 if (ret != -ENETRESET) {
1231 send_callback = true;
1232 event = STREAM_CBK_EVENT_DRAIN_READY;
1233 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1234 } else
1235 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001236 break;
1237 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001238 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001239 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001240 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001241 send_callback = true;
1242 event = STREAM_CBK_EVENT_DRAIN_READY;
1243 break;
1244 default:
1245 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1246 break;
1247 }
1248 pthread_mutex_lock(&out->lock);
1249 out->offload_thread_blocked = false;
1250 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001251 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001252 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001253 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001254 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001255 free(cmd);
1256 }
1257
1258 pthread_cond_signal(&out->cond);
1259 while (!list_empty(&out->offload_cmd_list)) {
1260 item = list_head(&out->offload_cmd_list);
1261 list_remove(item);
1262 free(node_to_item(item, struct offload_cmd, node));
1263 }
1264 pthread_mutex_unlock(&out->lock);
1265
1266 return NULL;
1267}
1268
1269static int create_offload_callback_thread(struct stream_out *out)
1270{
1271 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1272 list_init(&out->offload_cmd_list);
1273 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1274 offload_thread_loop, out);
1275 return 0;
1276}
1277
1278static int destroy_offload_callback_thread(struct stream_out *out)
1279{
1280 pthread_mutex_lock(&out->lock);
1281 stop_compressed_output_l(out);
1282 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1283
1284 pthread_mutex_unlock(&out->lock);
1285 pthread_join(out->offload_thread, (void **) NULL);
1286 pthread_cond_destroy(&out->offload_cond);
1287
1288 return 0;
1289}
1290
Eric Laurent07eeafd2013-10-06 12:52:49 -07001291static bool allow_hdmi_channel_config(struct audio_device *adev)
1292{
1293 struct listnode *node;
1294 struct audio_usecase *usecase;
1295 bool ret = true;
1296
1297 list_for_each(node, &adev->usecase_list) {
1298 usecase = node_to_item(node, struct audio_usecase, list);
1299 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1300 /*
1301 * If voice call is already existing, do not proceed further to avoid
1302 * disabling/enabling both RX and TX devices, CSD calls, etc.
1303 * Once the voice call done, the HDMI channels can be configured to
1304 * max channels of remaining use cases.
1305 */
1306 if (usecase->id == USECASE_VOICE_CALL) {
1307 ALOGD("%s: voice call is active, no change in HDMI channels",
1308 __func__);
1309 ret = false;
1310 break;
1311 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1312 ALOGD("%s: multi channel playback is active, "
1313 "no change in HDMI channels", __func__);
1314 ret = false;
1315 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001316 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001317 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001318 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1319 ", no change in HDMI channels", __func__,
1320 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001321 ret = false;
1322 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001323 }
1324 }
1325 }
1326 return ret;
1327}
1328
1329static int check_and_set_hdmi_channels(struct audio_device *adev,
1330 unsigned int channels)
1331{
1332 struct listnode *node;
1333 struct audio_usecase *usecase;
1334
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001335 unsigned int supported_channels = platform_edid_get_max_channels(
1336 adev->platform);
1337 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001338 /* Check if change in HDMI channel config is allowed */
1339 if (!allow_hdmi_channel_config(adev))
1340 return 0;
1341
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001342 if (channels > supported_channels)
1343 channels = supported_channels;
1344
Eric Laurent07eeafd2013-10-06 12:52:49 -07001345 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001346 ALOGD("%s: Requested channels are same as current channels(%d)",
1347 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001348 return 0;
1349 }
1350
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001351 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001352 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001353 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001354 adev->cur_hdmi_channels = channels;
1355
1356 /*
1357 * Deroute all the playback streams routed to HDMI so that
1358 * the back end is deactivated. Note that backend will not
1359 * be deactivated if any one stream is connected to it.
1360 */
1361 list_for_each(node, &adev->usecase_list) {
1362 usecase = node_to_item(node, struct audio_usecase, list);
1363 if (usecase->type == PCM_PLAYBACK &&
1364 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001365 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001366 }
1367 }
1368
1369 /*
1370 * Enable all the streams disabled above. Now the HDMI backend
1371 * will be activated with new channel configuration
1372 */
1373 list_for_each(node, &adev->usecase_list) {
1374 usecase = node_to_item(node, struct audio_usecase, list);
1375 if (usecase->type == PCM_PLAYBACK &&
1376 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001377 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001378 }
1379 }
1380
1381 return 0;
1382}
1383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384static int stop_output_stream(struct stream_out *out)
1385{
1386 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001387 struct audio_usecase *uc_info;
1388 struct audio_device *adev = out->dev;
1389
Eric Laurent994a6932013-07-17 11:51:42 -07001390 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001392 uc_info = get_usecase_from_list(adev, out->usecase);
1393 if (uc_info == NULL) {
1394 ALOGE("%s: Could not find the usecase (%d) in the list",
1395 __func__, out->usecase);
1396 return -EINVAL;
1397 }
1398
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001399 if (is_offload_usecase(out->usecase) &&
1400 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001401 if (adev->visualizer_stop_output != NULL)
1402 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001403
1404 audio_extn_dts_remove_state_notifier_node(out->usecase);
1405
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001406 if (adev->offload_effects_stop_output != NULL)
1407 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1408 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001409
Eric Laurent150dbfe2013-02-27 14:31:02 -08001410 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001411 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001412
1413 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001414 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001416 list_remove(&uc_info->list);
1417 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001419 if (is_offload_usecase(out->usecase) &&
1420 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1421 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1422 ALOGV("Disable passthrough , reset mixer to pcm");
1423 /* NO_PASSTHROUGH */
1424 out->compr_config.codec->compr_passthr = 0;
1425 audio_extn_dolby_set_hdmi_config(adev, out);
1426 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1427 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001428 /* Must be called after removing the usecase from list */
1429 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1430 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1431
Eric Laurent994a6932013-07-17 11:51:42 -07001432 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433 return ret;
1434}
1435
1436int start_output_stream(struct stream_out *out)
1437{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001439 int sink_channels = 0;
1440 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441 struct audio_usecase *uc_info;
1442 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301443 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001445 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1446 ret = -EINVAL;
1447 goto error_config;
1448 }
1449
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301450 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1451 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1452 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301453
Naresh Tanniru80659832014-06-04 18:17:56 +05301454 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301455 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301456 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301457 goto error_config;
1458 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301459
Eric Laurentb23d5282013-05-14 15:27:20 -07001460 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461 if (out->pcm_device_id < 0) {
1462 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1463 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001464 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001465 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466 }
1467
1468 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001469
1470 if (!uc_info) {
1471 ret = -ENOMEM;
1472 goto error_config;
1473 }
1474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 uc_info->id = out->usecase;
1476 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001477 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 uc_info->devices = out->devices;
1479 uc_info->in_snd_device = SND_DEVICE_NONE;
1480 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001481 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001482 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001483 if (is_offload_usecase(out->usecase)) {
1484 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001485 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1486 }
1487 }
Mingming Yin9c041392014-05-01 15:37:31 -07001488 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1489 if (!strncmp("true", prop_value, 4)) {
1490 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001491 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1492 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001493 check_and_set_hdmi_channels(adev, sink_channels);
1494 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001495 if (is_offload_usecase(out->usecase)) {
1496 unsigned int ch_count = out->compr_config.codec->ch_in;
1497 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1498 /* backend channel config for passthrough stream is stereo */
1499 ch_count = 2;
1500 check_and_set_hdmi_channels(adev, ch_count);
1501 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001502 check_and_set_hdmi_channels(adev, out->config.channels);
1503 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001504 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001505 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001506 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 select_devices(adev, out->usecase);
1509
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001510 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1511 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001512 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001513 unsigned int flags = PCM_OUT;
1514 unsigned int pcm_open_retry_count = 0;
1515 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1516 flags |= PCM_MMAP | PCM_NOIRQ;
1517 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1518 } else
1519 flags |= PCM_MONOTONIC;
1520
1521 while (1) {
1522 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1523 flags, &out->config);
1524 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1525 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1526 if (out->pcm != NULL) {
1527 pcm_close(out->pcm);
1528 out->pcm = NULL;
1529 }
1530 if (pcm_open_retry_count-- == 0) {
1531 ret = -EIO;
1532 goto error_open;
1533 }
1534 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1535 continue;
1536 }
1537 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001538 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001539 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1540 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001541 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001542 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1543 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001545 out->compr = compress_open(adev->snd_card,
1546 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 COMPRESS_IN, &out->compr_config);
1548 if (out->compr && !is_compress_ready(out->compr)) {
1549 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1550 compress_close(out->compr);
1551 out->compr = NULL;
1552 ret = -EIO;
1553 goto error_open;
1554 }
1555 if (out->offload_callback)
1556 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001557
Fred Oh3f43e742015-03-04 18:42:34 -08001558 /* Since small bufs uses blocking writes, a write will be blocked
1559 for the default max poll time (20s) in the event of an SSR.
1560 Reduce the poll time to observe and deal with SSR faster.
1561 */
1562 if (out->use_small_bufs) {
1563 compress_set_max_poll_wait(out->compr, 1000);
1564 }
1565
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001566 audio_extn_dts_create_state_notifier_node(out->usecase);
1567 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1568 popcount(out->channel_mask),
1569 out->playback_started);
1570
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001571#ifdef DS1_DOLBY_DDP_ENABLED
1572 if (audio_extn_is_dolby_format(out->format))
1573 audio_extn_dolby_send_ddp_endp_params(adev);
1574#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001575 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1576 if (adev->visualizer_start_output != NULL)
1577 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1578 if (adev->offload_effects_start_output != NULL)
1579 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001580 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001581 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 }
Eric Laurent994a6932013-07-17 11:51:42 -07001583 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001585error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001587error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001588 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589}
1590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591static int check_input_parameters(uint32_t sample_rate,
1592 audio_format_t format,
1593 int channel_count)
1594{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001595 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001597 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001598 !voice_extn_compress_voip_is_format_supported(format) &&
1599 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001600
1601 switch (channel_count) {
1602 case 1:
1603 case 2:
1604 case 6:
1605 break;
1606 default:
1607 ret = -EINVAL;
1608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609
1610 switch (sample_rate) {
1611 case 8000:
1612 case 11025:
1613 case 12000:
1614 case 16000:
1615 case 22050:
1616 case 24000:
1617 case 32000:
1618 case 44100:
1619 case 48000:
1620 break;
1621 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001622 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 }
1624
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001625 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626}
1627
1628static size_t get_input_buffer_size(uint32_t sample_rate,
1629 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001630 int channel_count,
1631 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632{
1633 size_t size = 0;
1634
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001635 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1636 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001638 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001639 if (is_low_latency)
1640 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001641 /* ToDo: should use frame_size computed based on the format and
1642 channel_count here. */
1643 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001645 /* make sure the size is multiple of 32 bytes
1646 * At 48 kHz mono 16-bit PCM:
1647 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1648 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1649 */
1650 size += 0x1f;
1651 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001652
1653 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001654}
1655
1656static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1657{
1658 struct stream_out *out = (struct stream_out *)stream;
1659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661}
1662
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001663static int out_set_sample_rate(struct audio_stream *stream __unused,
1664 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665{
1666 return -ENOSYS;
1667}
1668
1669static size_t out_get_buffer_size(const struct audio_stream *stream)
1670{
1671 struct stream_out *out = (struct stream_out *)stream;
1672
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001673 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001674 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001675 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1676 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001677
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001678 return out->config.period_size *
1679 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680}
1681
1682static uint32_t out_get_channels(const struct audio_stream *stream)
1683{
1684 struct stream_out *out = (struct stream_out *)stream;
1685
1686 return out->channel_mask;
1687}
1688
1689static audio_format_t out_get_format(const struct audio_stream *stream)
1690{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001691 struct stream_out *out = (struct stream_out *)stream;
1692
1693 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694}
1695
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001696static int out_set_format(struct audio_stream *stream __unused,
1697 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698{
1699 return -ENOSYS;
1700}
1701
1702static int out_standby(struct audio_stream *stream)
1703{
1704 struct stream_out *out = (struct stream_out *)stream;
1705 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001706
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301707 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1708 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001709 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1710 /* Ignore standby in case of voip call because the voip output
1711 * stream is closed in adev_close_output_stream()
1712 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301713 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001714 return 0;
1715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001719 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001721 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 if (out->pcm) {
1723 pcm_close(out->pcm);
1724 out->pcm = NULL;
1725 }
1726 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001727 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001729 out->gapless_mdata.encoder_delay = 0;
1730 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 if (out->compr != NULL) {
1732 compress_close(out->compr);
1733 out->compr = NULL;
1734 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001735 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001737 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 }
1739 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001740 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 return 0;
1742}
1743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001744static int out_dump(const struct audio_stream *stream __unused,
1745 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746{
1747 return 0;
1748}
1749
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001750static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1751{
1752 int ret = 0;
1753 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001754 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001755 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001756 tmp_mdata.encoder_delay = 0;
1757 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001758 tmp_mdata.min_blk_size = 0;
1759 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001760
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001761 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001762 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001763 return -EINVAL;
1764 }
1765
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001766 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1767 if (ret >= 0) {
1768 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1769 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1770 ALOGV("ADTS format is set in offload mode");
1771 }
1772 out->send_new_metadata = 1;
1773 }
1774
Mingming Yin3ee55c62014-08-04 14:23:35 -07001775 if (out->format == AUDIO_FORMAT_FLAC) {
1776 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1777 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001778 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001779 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1780 out->send_new_metadata = 1;
1781 }
1782 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1783 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001784 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001785 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1786 out->send_new_metadata = 1;
1787 }
1788 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1789 if (ret >= 0) {
1790 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1791 out->send_new_metadata = 1;
1792 }
1793 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1794 if (ret >= 0) {
1795 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1796 out->send_new_metadata = 1;
1797 }
1798 }
1799
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001800 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1801 if(ret >= 0)
1802 is_meta_data_params = true;
1803 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1804 if(ret >= 0 )
1805 is_meta_data_params = true;
1806 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1807 if(ret >= 0 )
1808 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001809 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1810 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001811 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001812 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001813 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1815 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001816 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001817 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001818 }
1819
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 if(!is_meta_data_params) {
1821 ALOGV("%s: Not gapless meta data params", __func__);
1822 return 0;
1823 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001824 out->gapless_mdata = tmp_mdata;
1825 out->send_new_metadata = 1;
1826 ALOGV("%s new encoder delay %u and padding %u", __func__,
1827 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1828
1829 return 0;
1830}
1831
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001832static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1833{
1834 return out == adev->primary_output || out == adev->voice_tx_output;
1835}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1838{
1839 struct stream_out *out = (struct stream_out *)stream;
1840 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001841 struct audio_usecase *usecase;
1842 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843 struct str_parms *parms;
1844 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001845 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001846 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847
sangwoobc677242013-08-08 16:53:43 +09001848 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001849 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301851 if (!parms)
1852 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001853 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1854 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001857 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001859 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301860 * When HDMI cable is unplugged/usb hs is disconnected the
1861 * music playback is paused and the policy manager sends routing=0
1862 * But the audioflingercontinues to write data until standby time
1863 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001864 * Avoid this by routing audio to speaker until standby.
1865 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301866 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1867 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001869 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1870 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001871 }
1872
1873 /*
1874 * select_devices() call below switches all the usecases on the same
1875 * backend to the new device. Refer to check_usecases_codec_backend() in
1876 * the select_devices(). But how do we undo this?
1877 *
1878 * For example, music playback is active on headset (deep-buffer usecase)
1879 * and if we go to ringtones and select a ringtone, low-latency usecase
1880 * will be started on headset+speaker. As we can't enable headset+speaker
1881 * and headset devices at the same time, select_devices() switches the music
1882 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1883 * So when the ringtone playback is completed, how do we undo the same?
1884 *
1885 * We are relying on the out_set_parameters() call on deep-buffer output,
1886 * once the ringtone playback is ended.
1887 * NOTE: We should not check if the current devices are same as new devices.
1888 * Because select_devices() must be called to switch back the music
1889 * playback to headset.
1890 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001891 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001892 out->devices = val;
1893
1894 if (!out->standby)
1895 select_devices(adev, out->usecase);
1896
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001897 if (output_drives_call(adev, out)) {
1898 if(!voice_is_in_call(adev)) {
1899 if (adev->mode == AUDIO_MODE_IN_CALL) {
1900 adev->current_call_output = out;
1901 ret = voice_start_call(adev);
1902 }
1903 } else {
1904 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001905 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001906 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001907 }
1908 }
1909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001911 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001913
1914 if (out == adev->primary_output) {
1915 pthread_mutex_lock(&adev->lock);
1916 audio_extn_set_parameters(adev, parms);
1917 pthread_mutex_unlock(&adev->lock);
1918 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001919 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001920 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001921 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001922
1923 audio_extn_dts_create_state_notifier_node(out->usecase);
1924 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1925 popcount(out->channel_mask),
1926 out->playback_started);
1927
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001928 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001929 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301932error:
Eric Laurent994a6932013-07-17 11:51:42 -07001933 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 return ret;
1935}
1936
1937static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1938{
1939 struct stream_out *out = (struct stream_out *)stream;
1940 struct str_parms *query = str_parms_create_str(keys);
1941 char *str;
1942 char value[256];
1943 struct str_parms *reply = str_parms_create();
1944 size_t i, j;
1945 int ret;
1946 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001947
1948 if (!query || !reply) {
1949 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1950 return NULL;
1951 }
1952
Eric Laurent994a6932013-07-17 11:51:42 -07001953 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1955 if (ret >= 0) {
1956 value[0] = '\0';
1957 i = 0;
1958 while (out->supported_channel_masks[i] != 0) {
1959 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1960 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1961 if (!first) {
1962 strcat(value, "|");
1963 }
1964 strcat(value, out_channels_name_to_enum_table[j].name);
1965 first = false;
1966 break;
1967 }
1968 }
1969 i++;
1970 }
1971 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1972 str = str_parms_to_str(reply);
1973 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001974 voice_extn_out_get_parameters(out, query, reply);
1975 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001976 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001977 free(str);
1978 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001979 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001981
1982 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1983 if (ret >= 0) {
1984 value[0] = '\0';
1985 i = 0;
1986 first = true;
1987 while (out->supported_formats[i] != 0) {
1988 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1989 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1990 if (!first) {
1991 strcat(value, "|");
1992 }
1993 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1994 first = false;
1995 break;
1996 }
1997 }
1998 i++;
1999 }
2000 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2001 str = str_parms_to_str(reply);
2002 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003 str_parms_destroy(query);
2004 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002005 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 return str;
2007}
2008
2009static uint32_t out_get_latency(const struct audio_stream_out *stream)
2010{
2011 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002012 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013
Alexy Josephaa54c872014-12-03 02:46:47 -08002014 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002015 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002016 } else {
2017 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002018 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002019 }
2020
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302021 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002022 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023}
2024
2025static int out_set_volume(struct audio_stream_out *stream, float left,
2026 float right)
2027{
Eric Laurenta9024de2013-04-04 09:19:12 -07002028 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 int volume[2];
2030
Eric Laurenta9024de2013-04-04 09:19:12 -07002031 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2032 /* only take left channel into account: the API is for stereo anyway */
2033 out->muted = (left == 0.0f);
2034 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002035 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002036 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2037 /*
2038 * Set mute or umute on HDMI passthrough stream.
2039 * Only take left channel into account.
2040 * Mute is 0 and unmute 1
2041 */
2042 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2043 } else {
2044 char mixer_ctl_name[128];
2045 struct audio_device *adev = out->dev;
2046 struct mixer_ctl *ctl;
2047 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002048 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002050 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2051 "Compress Playback %d Volume", pcm_device_id);
2052 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2053 if (!ctl) {
2054 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2055 __func__, mixer_ctl_name);
2056 return -EINVAL;
2057 }
2058 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2059 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2060 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2061 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002063 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065 return -ENOSYS;
2066}
2067
2068static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2069 size_t bytes)
2070{
2071 struct stream_out *out = (struct stream_out *)stream;
2072 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302073 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002074 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302077
Naresh Tanniru80659832014-06-04 18:17:56 +05302078 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002079 // increase written size during SSR to avoid mismatch
2080 // with the written frames count in AF
2081 if (!is_offload_usecase(out->usecase))
2082 out->written += bytes / (out->config.channels * sizeof(short));
2083
Naresh Tanniru80659832014-06-04 18:17:56 +05302084 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302085 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302086 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302087 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002088 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302089 //during SSR for compress usecase we should return error to flinger
2090 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2091 pthread_mutex_unlock(&out->lock);
2092 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302093 }
2094 }
2095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002097 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002098 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002099 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2100 ret = voice_extn_compress_voip_start_output_stream(out);
2101 else
2102 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002103 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002104 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002106 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 goto exit;
2108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002111 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002112 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002113 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002114 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002115 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2116 out->send_new_metadata = 0;
2117 }
2118
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302120 if (ret < 0)
2121 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002122 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002123 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302124 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302126 } else if (-ENETRESET == ret) {
2127 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2128 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2129 pthread_mutex_unlock(&out->lock);
2130 out_standby(&out->stream.common);
2131 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302133 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 compress_start(out->compr);
2135 out->playback_started = 1;
2136 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002137
2138 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2139 popcount(out->channel_mask),
2140 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 }
2142 pthread_mutex_unlock(&out->lock);
2143 return ret;
2144 } else {
2145 if (out->pcm) {
2146 if (out->muted)
2147 memset((void *)buffer, 0, bytes);
2148 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002149 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2150 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2151 else
2152 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302153 if (ret < 0)
2154 ret = -errno;
2155 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002156 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 }
2159
2160exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302161 /* ToDo: There may be a corner case when SSR happens back to back during
2162 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302163 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302164 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165 }
2166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 pthread_mutex_unlock(&out->lock);
2168
2169 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002170 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002171 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302172 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302173 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302174 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302175 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302176 out->standby = true;
2177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002179 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302180 out_get_sample_rate(&out->stream.common));
2181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 }
2183 return bytes;
2184}
2185
2186static int out_get_render_position(const struct audio_stream_out *stream,
2187 uint32_t *dsp_frames)
2188{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302190 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002191 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002192 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002193 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002194 pthread_mutex_lock(&out->lock);
2195 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302196 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002197 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302198 if (ret < 0)
2199 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 ALOGVV("%s rendered frames %d sample_rate %d",
2201 __func__, *dsp_frames, out->sample_rate);
2202 }
2203 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302204 if (-ENETRESET == ret) {
2205 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2206 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2207 return -EINVAL;
2208 } else if(ret < 0) {
2209 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2210 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302211 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2212 /*
2213 * Handle corner case where compress session is closed during SSR
2214 * and timestamp is queried
2215 */
2216 ALOGE(" ERROR: sound card not active, return error");
2217 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302218 } else {
2219 return 0;
2220 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 } else
2222 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223}
2224
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002225static int out_add_audio_effect(const struct audio_stream *stream __unused,
2226 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227{
2228 return 0;
2229}
2230
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002231static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2232 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233{
2234 return 0;
2235}
2236
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002237static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2238 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239{
2240 return -EINVAL;
2241}
2242
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002243static int out_get_presentation_position(const struct audio_stream_out *stream,
2244 uint64_t *frames, struct timespec *timestamp)
2245{
2246 struct stream_out *out = (struct stream_out *)stream;
2247 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002248 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002249
2250 pthread_mutex_lock(&out->lock);
2251
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002252 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002253 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302254 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002255 &out->sample_rate);
2256 ALOGVV("%s rendered frames %ld sample_rate %d",
2257 __func__, dsp_frames, out->sample_rate);
2258 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302259 if (ret < 0)
2260 ret = -errno;
2261 if (-ENETRESET == ret) {
2262 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2263 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2264 ret = -EINVAL;
2265 } else
2266 ret = 0;
2267
Eric Laurent949a0892013-09-20 09:20:13 -07002268 /* this is the best we can do */
2269 clock_gettime(CLOCK_MONOTONIC, timestamp);
2270 }
2271 } else {
2272 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002273 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002274 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2275 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002276 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002277 // This adjustment accounts for buffering after app processor.
2278 // It is based on estimated DSP latency per use case, rather than exact.
2279 signed_frames -=
2280 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2281
Eric Laurent949a0892013-09-20 09:20:13 -07002282 // It would be unusual for this value to be negative, but check just in case ...
2283 if (signed_frames >= 0) {
2284 *frames = signed_frames;
2285 ret = 0;
2286 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002287 }
2288 }
2289 }
2290
2291 pthread_mutex_unlock(&out->lock);
2292
2293 return ret;
2294}
2295
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002296static int out_set_callback(struct audio_stream_out *stream,
2297 stream_callback_t callback, void *cookie)
2298{
2299 struct stream_out *out = (struct stream_out *)stream;
2300
2301 ALOGV("%s", __func__);
2302 pthread_mutex_lock(&out->lock);
2303 out->offload_callback = callback;
2304 out->offload_cookie = cookie;
2305 pthread_mutex_unlock(&out->lock);
2306 return 0;
2307}
2308
2309static int out_pause(struct audio_stream_out* stream)
2310{
2311 struct stream_out *out = (struct stream_out *)stream;
2312 int status = -ENOSYS;
2313 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002314 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002315 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002316 pthread_mutex_lock(&out->lock);
2317 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302318 struct audio_device *adev = out->dev;
2319 int snd_scard_state = get_snd_card_state(adev);
2320
2321 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2322 status = compress_pause(out->compr);
2323
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002325
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302326 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002327 audio_extn_dts_notify_playback_state(out->usecase, 0,
2328 out->sample_rate, popcount(out->channel_mask),
2329 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330 }
2331 pthread_mutex_unlock(&out->lock);
2332 }
2333 return status;
2334}
2335
2336static int out_resume(struct audio_stream_out* stream)
2337{
2338 struct stream_out *out = (struct stream_out *)stream;
2339 int status = -ENOSYS;
2340 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002341 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002342 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 status = 0;
2344 pthread_mutex_lock(&out->lock);
2345 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302346 struct audio_device *adev = out->dev;
2347 int snd_scard_state = get_snd_card_state(adev);
2348
2349 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2350 status = compress_resume(out->compr);
2351
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002353
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302354 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002355 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2356 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 }
2358 pthread_mutex_unlock(&out->lock);
2359 }
2360 return status;
2361}
2362
2363static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 int status = -ENOSYS;
2367 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002368 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 pthread_mutex_lock(&out->lock);
2370 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2371 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2372 else
2373 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2374 pthread_mutex_unlock(&out->lock);
2375 }
2376 return status;
2377}
2378
2379static int out_flush(struct audio_stream_out* stream)
2380{
2381 struct stream_out *out = (struct stream_out *)stream;
2382 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002383 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002384 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 pthread_mutex_lock(&out->lock);
2386 stop_compressed_output_l(out);
2387 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002388 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 return 0;
2390 }
2391 return -ENOSYS;
2392}
2393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394/** audio_stream_in implementation **/
2395static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2396{
2397 struct stream_in *in = (struct stream_in *)stream;
2398
2399 return in->config.rate;
2400}
2401
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002402static int in_set_sample_rate(struct audio_stream *stream __unused,
2403 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404{
2405 return -ENOSYS;
2406}
2407
2408static size_t in_get_buffer_size(const struct audio_stream *stream)
2409{
2410 struct stream_in *in = (struct stream_in *)stream;
2411
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002412 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2413 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002414 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2415 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002416
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002417 return in->config.period_size *
2418 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419}
2420
2421static uint32_t in_get_channels(const struct audio_stream *stream)
2422{
2423 struct stream_in *in = (struct stream_in *)stream;
2424
2425 return in->channel_mask;
2426}
2427
2428static audio_format_t in_get_format(const struct audio_stream *stream)
2429{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002430 struct stream_in *in = (struct stream_in *)stream;
2431
2432 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433}
2434
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002435static int in_set_format(struct audio_stream *stream __unused,
2436 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437{
2438 return -ENOSYS;
2439}
2440
2441static int in_standby(struct audio_stream *stream)
2442{
2443 struct stream_in *in = (struct stream_in *)stream;
2444 struct audio_device *adev = in->dev;
2445 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302446 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2447 stream, in->usecase, use_case_table[in->usecase]);
2448
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002449 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2450 /* Ignore standby in case of voip call because the voip input
2451 * stream is closed in adev_close_input_stream()
2452 */
2453 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2454 return status;
2455 }
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002458 if (!in->standby && in->is_st_session) {
2459 ALOGD("%s: sound trigger pcm stop lab", __func__);
2460 audio_extn_sound_trigger_stop_lab(in);
2461 in->standby = 1;
2462 }
2463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002465 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002467 if (in->pcm) {
2468 pcm_close(in->pcm);
2469 in->pcm = NULL;
2470 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002472 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 }
2474 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002475 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 return status;
2477}
2478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002479static int in_dump(const struct audio_stream *stream __unused,
2480 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481{
2482 return 0;
2483}
2484
2485static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2486{
2487 struct stream_in *in = (struct stream_in *)stream;
2488 struct audio_device *adev = in->dev;
2489 struct str_parms *parms;
2490 char *str;
2491 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002492 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302494 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 parms = str_parms_create_str(kvpairs);
2496
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302497 if (!parms)
2498 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002500 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002501
2502 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2503 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 val = atoi(value);
2505 /* no audio source uses val == 0 */
2506 if ((in->source != val) && (val != 0)) {
2507 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002508 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2509 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2510 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2511 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002512 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002513 err = voice_extn_compress_voip_open_input_stream(in);
2514 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002515 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002516 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002517 }
2518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 }
2520 }
2521
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002522 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2523 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002525 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 in->device = val;
2527 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002528 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002529 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 }
2531 }
2532
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002533done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002535 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536
2537 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302538error:
Eric Laurent994a6932013-07-17 11:51:42 -07002539 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 return ret;
2541}
2542
2543static char* in_get_parameters(const struct audio_stream *stream,
2544 const char *keys)
2545{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002546 struct stream_in *in = (struct stream_in *)stream;
2547 struct str_parms *query = str_parms_create_str(keys);
2548 char *str;
2549 char value[256];
2550 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002551
2552 if (!query || !reply) {
2553 ALOGE("in_get_parameters: failed to create query or reply");
2554 return NULL;
2555 }
2556
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002557 ALOGV("%s: enter: keys - %s", __func__, keys);
2558
2559 voice_extn_in_get_parameters(in, query, reply);
2560
2561 str = str_parms_to_str(reply);
2562 str_parms_destroy(query);
2563 str_parms_destroy(reply);
2564
2565 ALOGV("%s: exit: returns - %s", __func__, str);
2566 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567}
2568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002569static int in_set_gain(struct audio_stream_in *stream __unused,
2570 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571{
2572 return 0;
2573}
2574
2575static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2576 size_t bytes)
2577{
2578 struct stream_in *in = (struct stream_in *)stream;
2579 struct audio_device *adev = in->dev;
2580 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302581 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302584
2585 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302586 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302587 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302588 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302589 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002590 } else {
2591 if (in->is_st_session && !in->is_st_session_active) {
2592 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2593 ret= -EIO;;
2594 goto exit;
2595 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302596 }
2597 }
2598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002600 if (!in->is_st_session) {
2601 pthread_mutex_lock(&adev->lock);
2602 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2603 ret = voice_extn_compress_voip_start_input_stream(in);
2604 else
2605 ret = start_input_stream(in);
2606 pthread_mutex_unlock(&adev->lock);
2607 if (ret != 0) {
2608 goto exit;
2609 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 }
2611 in->standby = 0;
2612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613
2614 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002615 if (audio_extn_ssr_get_enabled() &&
2616 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002617 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002618 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2619 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002620 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2621 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002622 else
2623 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302624 if (ret < 0)
2625 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 }
2627
2628 /*
2629 * Instead of writing zeroes here, we could trust the hardware
2630 * to always provide zeroes when muted.
2631 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302632 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2633 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 memset(buffer, 0, bytes);
2635
2636exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302637 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302638 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302639 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002640 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2641 session reading on LAB data. In this case do not set sound card state
2642 offline, instead mark this sound trigger session inactive to avoid
2643 further reading of LAB data from CPE driver. Marking the session
2644 inactive handles both CPE and ADSP SSR for sound trigger session */
2645 if (!in->is_st_session)
2646 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2647 else
2648 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302649 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 pthread_mutex_unlock(&in->lock);
2651
2652 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302653 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302654 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302655 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302656 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302657 in->standby = true;
2658 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302659 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002661 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002662 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302663 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 }
2665 return bytes;
2666}
2667
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002668static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669{
2670 return 0;
2671}
2672
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002673static int add_remove_audio_effect(const struct audio_stream *stream,
2674 effect_handle_t effect,
2675 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002677 struct stream_in *in = (struct stream_in *)stream;
2678 int status = 0;
2679 effect_descriptor_t desc;
2680
2681 status = (*effect)->get_descriptor(effect, &desc);
2682 if (status != 0)
2683 return status;
2684
2685 pthread_mutex_lock(&in->lock);
2686 pthread_mutex_lock(&in->dev->lock);
2687 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2688 in->enable_aec != enable &&
2689 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2690 in->enable_aec = enable;
2691 if (!in->standby)
2692 select_devices(in->dev, in->usecase);
2693 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002694 if (in->enable_ns != enable &&
2695 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2696 in->enable_ns = enable;
2697 if (!in->standby)
2698 select_devices(in->dev, in->usecase);
2699 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002700 pthread_mutex_unlock(&in->dev->lock);
2701 pthread_mutex_unlock(&in->lock);
2702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 return 0;
2704}
2705
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002706static int in_add_audio_effect(const struct audio_stream *stream,
2707 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
Eric Laurent994a6932013-07-17 11:51:42 -07002709 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710 return add_remove_audio_effect(stream, effect, true);
2711}
2712
2713static int in_remove_audio_effect(const struct audio_stream *stream,
2714 effect_handle_t effect)
2715{
Eric Laurent994a6932013-07-17 11:51:42 -07002716 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002717 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718}
2719
2720static int adev_open_output_stream(struct audio_hw_device *dev,
2721 audio_io_handle_t handle,
2722 audio_devices_t devices,
2723 audio_output_flags_t flags,
2724 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002725 struct audio_stream_out **stream_out,
2726 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727{
2728 struct audio_device *adev = (struct audio_device *)dev;
2729 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002730 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002731 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302734
2735 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2736 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2737 ALOGE(" sound card is not active rejecting compress output open request");
2738 return -EINVAL;
2739 }
2740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2742
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302743 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2744 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2745 devices, flags, &out->stream);
2746
2747
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002748 if (!out) {
2749 return -ENOMEM;
2750 }
2751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002752 if (devices == AUDIO_DEVICE_NONE)
2753 devices = AUDIO_DEVICE_OUT_SPEAKER;
2754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 out->flags = flags;
2756 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002757 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002758 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002759 out->sample_rate = config->sample_rate;
2760 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2761 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002762 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002763 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002764 out->non_blocking = 0;
2765 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766
2767 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002768 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2769 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2770 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2771
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002772 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002773 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2774 ret = read_hdmi_channel_masks(out);
2775
2776 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2777 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002778 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002779 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002780 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002781
2782 if (config->sample_rate == 0)
2783 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2784 if (config->channel_mask == 0)
2785 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2786
2787 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002788 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2790 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002792 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002794 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2795 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002796 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002797 ret = voice_extn_compress_voip_open_output_stream(out);
2798 if (ret != 0) {
2799 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2800 __func__, ret);
2801 goto error_open;
2802 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002803 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2804 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2805 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2806 ALOGE("%s: Unsupported Offload information", __func__);
2807 ret = -EINVAL;
2808 goto error_open;
2809 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002810
2811 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2812 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2813 ALOGV("read and update_pass through formats");
2814 ret = audio_extn_dolby_update_passt_formats(adev, out);
2815 if(ret != 0) {
2816 goto error_open;
2817 }
2818 if(config->offload_info.format == 0)
2819 config->offload_info.format = out->supported_formats[0];
2820 }
2821
Mingming Yin90310102013-11-13 16:57:00 -08002822 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002823 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 ALOGE("%s: Unsupported audio format", __func__);
2825 ret = -EINVAL;
2826 goto error_open;
2827 }
2828
2829 out->compr_config.codec = (struct snd_codec *)
2830 calloc(1, sizeof(struct snd_codec));
2831
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002832 if (!out->compr_config.codec) {
2833 ret = -ENOMEM;
2834 goto error_open;
2835 }
2836
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002837 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 if (config->offload_info.channel_mask)
2839 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002840 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002842 config->offload_info.channel_mask = config->channel_mask;
2843 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002844 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 out->sample_rate = config->offload_info.sample_rate;
2846
2847 out->stream.set_callback = out_set_callback;
2848 out->stream.pause = out_pause;
2849 out->stream.resume = out_resume;
2850 out->stream.drain = out_drain;
2851 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002852 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002854 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002855 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002856 audio_extn_dolby_get_snd_codec_id(adev, out,
2857 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002858 else
2859 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002861 if (audio_is_offload_pcm(config->offload_info.format)) {
2862 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002863 platform_get_pcm_offload_buffer_size(&config->offload_info);
2864 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2865 out->compr_config.fragment_size =
2866 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002867 } else {
2868 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002869 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002870 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2872 out->compr_config.codec->sample_rate =
2873 compress_get_alsa_rate(config->offload_info.sample_rate);
2874 out->compr_config.codec->bit_rate =
2875 config->offload_info.bit_rate;
2876 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002877 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002879 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002880 /*TODO: Do we need to change it for passthrough */
2881 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882
Mingming Yin3ee55c62014-08-04 14:23:35 -07002883 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2884 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002885 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2886 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002887 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002888 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2889
Mingming Yin3ee55c62014-08-04 14:23:35 -07002890 if (out->bit_width == 24) {
2891 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2892 }
2893
Amit Shekhar6f461b12014-08-01 14:52:58 -07002894 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002895 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002896
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2898 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002899
Alexy Josephaa54c872014-12-03 02:46:47 -08002900 if (config->offload_info.use_small_bufs) {
2901 //this flag is set from framework only if its for PCM formats
2902 //no need to check for PCM format again
2903 out->non_blocking = 0;
2904 out->use_small_bufs = true;
2905 ALOGI("Keep write blocking for small buff: non_blockling %d",
2906 out->non_blocking);
2907 }
2908
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002909 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002910 out->offload_state = OFFLOAD_STATE_IDLE;
2911 out->playback_started = 0;
2912
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002913 audio_extn_dts_create_state_notifier_node(out->usecase);
2914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 create_offload_callback_thread(out);
2916 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2917 __func__, config->offload_info.version,
2918 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002919 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002920 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002921 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2922 ret = voice_check_and_set_incall_music_usecase(adev, out);
2923 if (ret != 0) {
2924 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2925 __func__, ret);
2926 goto error_open;
2927 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002928 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2929 if (config->sample_rate == 0)
2930 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2931 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2932 config->sample_rate != 8000) {
2933 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2934 ret = -EINVAL;
2935 goto error_open;
2936 }
2937 out->sample_rate = config->sample_rate;
2938 out->config.rate = config->sample_rate;
2939 if (config->format == AUDIO_FORMAT_DEFAULT)
2940 config->format = AUDIO_FORMAT_PCM_16_BIT;
2941 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2942 config->format = AUDIO_FORMAT_PCM_16_BIT;
2943 ret = -EINVAL;
2944 goto error_open;
2945 }
2946 out->format = config->format;
2947 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2948 out->config = pcm_config_afe_proxy_playback;
2949 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002950 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002951 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2953 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002954 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002955 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2956 format = AUDIO_FORMAT_PCM_16_BIT;
2957 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2958 out->config = pcm_config_deep_buffer;
2959 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002960 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002961 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002962 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002963 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002964 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002965 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 }
2967
Amit Shekhar1d896042014-10-03 13:16:09 -07002968 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2969 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002970 /* TODO remove this hardcoding and check why width is zero*/
2971 if (out->bit_width == 0)
2972 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002973 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2974 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002975 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002976 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002977 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2978 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2979 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002980 if(adev->primary_output == NULL)
2981 adev->primary_output = out;
2982 else {
2983 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002984 ret = -EEXIST;
2985 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002986 }
2987 }
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 /* Check if this usecase is already existing */
2990 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002991 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2992 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002995 ret = -EEXIST;
2996 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 }
2998 pthread_mutex_unlock(&adev->lock);
2999
3000 out->stream.common.get_sample_rate = out_get_sample_rate;
3001 out->stream.common.set_sample_rate = out_set_sample_rate;
3002 out->stream.common.get_buffer_size = out_get_buffer_size;
3003 out->stream.common.get_channels = out_get_channels;
3004 out->stream.common.get_format = out_get_format;
3005 out->stream.common.set_format = out_set_format;
3006 out->stream.common.standby = out_standby;
3007 out->stream.common.dump = out_dump;
3008 out->stream.common.set_parameters = out_set_parameters;
3009 out->stream.common.get_parameters = out_get_parameters;
3010 out->stream.common.add_audio_effect = out_add_audio_effect;
3011 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3012 out->stream.get_latency = out_get_latency;
3013 out->stream.set_volume = out_set_volume;
3014 out->stream.write = out_write;
3015 out->stream.get_render_position = out_get_render_position;
3016 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003017 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003020 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003021 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003023 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3024 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 config->format = out->stream.common.get_format(&out->stream.common);
3027 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3028 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3029
3030 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303031 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3032 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003033
3034 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3035 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3036 popcount(out->channel_mask), out->playback_started);
3037
Eric Laurent994a6932013-07-17 11:51:42 -07003038 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003040
3041error_open:
3042 free(out);
3043 *stream_out = NULL;
3044 ALOGD("%s: exit: ret %d", __func__, ret);
3045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046}
3047
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003048static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 struct audio_stream_out *stream)
3050{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 struct stream_out *out = (struct stream_out *)stream;
3052 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003053 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303055 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3056
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303058 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003059 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303060 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061 if(ret != 0)
3062 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3063 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003064 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003065 out_standby(&stream->common);
3066
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003067 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003068 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003070 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 if (out->compr_config.codec != NULL)
3072 free(out->compr_config.codec);
3073 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003074
3075 if (adev->voice_tx_output == out)
3076 adev->voice_tx_output = NULL;
3077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003078 pthread_cond_destroy(&out->cond);
3079 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003081 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082}
3083
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003084static void close_compress_sessions(struct audio_device *adev)
3085{
Mingming Yin7b762e72015-03-04 13:47:32 -08003086 struct stream_out *out;
3087 struct listnode *node;
3088 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003089 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003090 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003091 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003092 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003093 if (usecase && usecase->stream.out) {
3094 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3095 out = usecase->stream.out;
3096 pthread_mutex_unlock(&adev->lock);
3097 out_standby(&out->stream.common);
3098 pthread_mutex_lock(&adev->lock);
3099 }
3100 }
3101 }
3102 pthread_mutex_unlock(&adev->lock);
3103}
3104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3106{
3107 struct audio_device *adev = (struct audio_device *)dev;
3108 struct str_parms *parms;
3109 char *str;
3110 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003111 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003112 int ret;
3113 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003115 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303118 if (!parms)
3119 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003120 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3121 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303122 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303123 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303124 struct listnode *node;
3125 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303126 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303127 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003128 //close compress sessions on OFFLINE status
3129 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303130 } else if (strstr(snd_card_status, "ONLINE")) {
3131 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303132 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303133 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303134 }
3135
3136 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003137 status = voice_set_parameters(adev, parms);
3138 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003139 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003141 status = platform_set_parameters(adev->platform, parms);
3142 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003143 goto done;
3144
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003145 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3146 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003147 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3149 adev->bluetooth_nrec = true;
3150 else
3151 adev->bluetooth_nrec = false;
3152 }
3153
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003154 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3155 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3157 adev->screen_off = false;
3158 else
3159 adev->screen_off = true;
3160 }
3161
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003162 ret = str_parms_get_int(parms, "rotation", &val);
3163 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003164 bool reverse_speakers = false;
3165 switch(val) {
3166 // FIXME: note that the code below assumes that the speakers are in the correct placement
3167 // relative to the user when the device is rotated 90deg from its default rotation. This
3168 // assumption is device-specific, not platform-specific like this code.
3169 case 270:
3170 reverse_speakers = true;
3171 break;
3172 case 0:
3173 case 90:
3174 case 180:
3175 break;
3176 default:
3177 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003179 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 if (status == 0) {
3181 if (adev->speaker_lr_swap != reverse_speakers) {
3182 adev->speaker_lr_swap = reverse_speakers;
3183 // only update the selected device if there is active pcm playback
3184 struct audio_usecase *usecase;
3185 struct listnode *node;
3186 list_for_each(node, &adev->usecase_list) {
3187 usecase = node_to_item(node, struct audio_usecase, list);
3188 if (usecase->type == PCM_PLAYBACK) {
3189 select_devices(adev, usecase->id);
3190 break;
3191 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003192 }
3193 }
3194 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003195 }
3196
Mingming Yin514a8bc2014-07-29 15:22:21 -07003197 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3198 if (ret >= 0) {
3199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3200 adev->bt_wb_speech_enabled = true;
3201 else
3202 adev->bt_wb_speech_enabled = false;
3203 }
3204
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003205 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3206 if (ret >= 0) {
3207 val = atoi(value);
3208 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3209 ALOGV("cache new edid");
3210 platform_cache_edid(adev->platform);
3211 }
3212 }
3213
3214 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3215 if (ret >= 0) {
3216 val = atoi(value);
3217 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3218 ALOGV("invalidate cached edid");
3219 platform_invalidate_edid(adev->platform);
3220 }
3221 }
3222
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003223 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003224
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003225done:
3226 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003227 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303228error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003229 ALOGV("%s: exit with code(%d)", __func__, status);
3230 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231}
3232
3233static char* adev_get_parameters(const struct audio_hw_device *dev,
3234 const char *keys)
3235{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003236 struct audio_device *adev = (struct audio_device *)dev;
3237 struct str_parms *reply = str_parms_create();
3238 struct str_parms *query = str_parms_create_str(keys);
3239 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303240 char value[256] = {0};
3241 int ret = 0;
3242
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003243 if (!query || !reply) {
3244 ALOGE("adev_get_parameters: failed to create query or reply");
3245 return NULL;
3246 }
3247
Naresh Tannirud7205b62014-06-20 02:54:48 +05303248 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3249 sizeof(value));
3250 if (ret >=0) {
3251 int val = 1;
3252 pthread_mutex_lock(&adev->snd_card_status.lock);
3253 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3254 val = 0;
3255 pthread_mutex_unlock(&adev->snd_card_status.lock);
3256 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3257 goto exit;
3258 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003259
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003260 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003261 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003262 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003263 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303264 pthread_mutex_unlock(&adev->lock);
3265
Naresh Tannirud7205b62014-06-20 02:54:48 +05303266exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003267 str = str_parms_to_str(reply);
3268 str_parms_destroy(query);
3269 str_parms_destroy(reply);
3270
3271 ALOGV("%s: exit: returns - %s", __func__, str);
3272 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273}
3274
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003275static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276{
3277 return 0;
3278}
3279
3280static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3281{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003282 int ret;
3283 struct audio_device *adev = (struct audio_device *)dev;
3284 pthread_mutex_lock(&adev->lock);
3285 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003286 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003287 pthread_mutex_unlock(&adev->lock);
3288 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289}
3290
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003291static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3292 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293{
3294 return -ENOSYS;
3295}
3296
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003297static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3298 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299{
3300 return -ENOSYS;
3301}
3302
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003303static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3304 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305{
3306 return -ENOSYS;
3307}
3308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003309static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3310 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311{
3312 return -ENOSYS;
3313}
3314
3315static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3316{
3317 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 pthread_mutex_lock(&adev->lock);
3320 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003321 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003323 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3324 voice_is_in_call(adev)) {
3325 voice_stop_call(adev);
3326 adev->current_call_output = NULL;
3327 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 }
3329 pthread_mutex_unlock(&adev->lock);
3330 return 0;
3331}
3332
3333static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3334{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003335 int ret;
3336
3337 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003338 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003339 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3340 pthread_mutex_unlock(&adev->lock);
3341
3342 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343}
3344
3345static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3346{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003347 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 return 0;
3349}
3350
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003351static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 const struct audio_config *config)
3353{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003354 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003356 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3357 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358}
3359
3360static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003361 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 audio_devices_t devices,
3363 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003364 struct audio_stream_in **stream_in,
3365 audio_input_flags_t flags __unused,
3366 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003367 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368{
3369 struct audio_device *adev = (struct audio_device *)dev;
3370 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003371 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003372 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003373 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 *stream_in = NULL;
3376 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3377 return -EINVAL;
3378
3379 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003380
3381 if (!in) {
3382 ALOGE("failed to allocate input stream");
3383 return -ENOMEM;
3384 }
3385
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303386 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003387 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3388 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003390 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 in->stream.common.get_sample_rate = in_get_sample_rate;
3393 in->stream.common.set_sample_rate = in_set_sample_rate;
3394 in->stream.common.get_buffer_size = in_get_buffer_size;
3395 in->stream.common.get_channels = in_get_channels;
3396 in->stream.common.get_format = in_get_format;
3397 in->stream.common.set_format = in_set_format;
3398 in->stream.common.standby = in_standby;
3399 in->stream.common.dump = in_dump;
3400 in->stream.common.set_parameters = in_set_parameters;
3401 in->stream.common.get_parameters = in_get_parameters;
3402 in->stream.common.add_audio_effect = in_add_audio_effect;
3403 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3404 in->stream.set_gain = in_set_gain;
3405 in->stream.read = in_read;
3406 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3407
3408 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003409 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 in->standby = 1;
3412 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003413 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414
3415 /* Update config params with the requested sample rate and channels */
3416 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003417 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3418 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3419 is_low_latency = true;
3420#if LOW_LATENCY_CAPTURE_USE_CASE
3421 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3422#endif
3423 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003426 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003428 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303429 if (adev->mode != AUDIO_MODE_IN_CALL) {
3430 ret = -EINVAL;
3431 goto err_open;
3432 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003433 if (config->sample_rate == 0)
3434 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3435 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3436 config->sample_rate != 8000) {
3437 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3438 ret = -EINVAL;
3439 goto err_open;
3440 }
3441 if (config->format == AUDIO_FORMAT_DEFAULT)
3442 config->format = AUDIO_FORMAT_PCM_16_BIT;
3443 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3444 config->format = AUDIO_FORMAT_PCM_16_BIT;
3445 ret = -EINVAL;
3446 goto err_open;
3447 }
3448
3449 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3450 in->config = pcm_config_afe_proxy_record;
3451 in->config.channels = channel_count;
3452 in->config.rate = config->sample_rate;
3453 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003454 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003455 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003456 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3457 ret = -EINVAL;
3458 goto err_open;
3459 }
3460 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003461 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003462 }
Mingming Yine62d7842013-10-25 16:26:03 -07003463 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003464 audio_extn_compr_cap_format_supported(config->format) &&
3465 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003466 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003467 } else {
3468 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003469 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003470 buffer_size = get_input_buffer_size(config->sample_rate,
3471 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003472 channel_count,
3473 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003474 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003475 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3476 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3477 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3478 (in->config.rate == 8000 || in->config.rate == 16000) &&
3479 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3480 voice_extn_compress_voip_open_input_stream(in);
3481 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003482 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003484 /* This stream could be for sound trigger lab,
3485 get sound trigger pcm if present */
3486 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303487 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003490 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003491 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492
3493err_open:
3494 free(in);
3495 *stream_in = NULL;
3496 return ret;
3497}
3498
3499static void adev_close_input_stream(struct audio_hw_device *dev,
3500 struct audio_stream_in *stream)
3501{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003502 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003503 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003504 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303505
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303506 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003507
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303508 /* Disable echo reference while closing input stream */
3509 platform_set_echo_reference(adev->platform, false);
3510
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003511 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303512 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003513 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303514 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003515 if (ret != 0)
3516 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3517 __func__, ret);
3518 } else
3519 in_standby(&stream->common);
3520
Mingming Yin7b762e72015-03-04 13:47:32 -08003521 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003522 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003523 audio_extn_ssr_deinit();
3524 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525
Mingming Yine62d7842013-10-25 16:26:03 -07003526 if(audio_extn_compr_cap_enabled() &&
3527 audio_extn_compr_cap_format_supported(in->config.format))
3528 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003529
3530 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 return;
3532}
3533
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003534static int adev_dump(const audio_hw_device_t *device __unused,
3535 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536{
3537 return 0;
3538}
3539
3540static int adev_close(hw_device_t *device)
3541{
3542 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003543
3544 if (!adev)
3545 return 0;
3546
3547 pthread_mutex_lock(&adev_init_lock);
3548
3549 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003550 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003551 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003552 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003553 audio_route_free(adev->audio_route);
3554 free(adev->snd_dev_ref_cnt);
3555 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003556 free(device);
3557 adev = NULL;
3558 }
3559 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 return 0;
3561}
3562
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003563/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3564 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3565 * just that it _might_ work.
3566 */
3567static int period_size_is_plausible_for_low_latency(int period_size)
3568{
3569 switch (period_size) {
3570 case 160:
3571 case 240:
3572 case 320:
3573 case 480:
3574 return 1;
3575 default:
3576 return 0;
3577 }
3578}
3579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580static int adev_open(const hw_module_t *module, const char *name,
3581 hw_device_t **device)
3582{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003583 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003585 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3587
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003588 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003589 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003590 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003591 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003592 ALOGD("%s: returning existing instance of adev", __func__);
3593 ALOGD("%s: exit", __func__);
3594 pthread_mutex_unlock(&adev_init_lock);
3595 return 0;
3596 }
3597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598 adev = calloc(1, sizeof(struct audio_device));
3599
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003600 if (!adev) {
3601 pthread_mutex_unlock(&adev_init_lock);
3602 return -ENOMEM;
3603 }
3604
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003605 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3608 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3609 adev->device.common.module = (struct hw_module_t *)module;
3610 adev->device.common.close = adev_close;
3611
3612 adev->device.init_check = adev_init_check;
3613 adev->device.set_voice_volume = adev_set_voice_volume;
3614 adev->device.set_master_volume = adev_set_master_volume;
3615 adev->device.get_master_volume = adev_get_master_volume;
3616 adev->device.set_master_mute = adev_set_master_mute;
3617 adev->device.get_master_mute = adev_get_master_mute;
3618 adev->device.set_mode = adev_set_mode;
3619 adev->device.set_mic_mute = adev_set_mic_mute;
3620 adev->device.get_mic_mute = adev_get_mic_mute;
3621 adev->device.set_parameters = adev_set_parameters;
3622 adev->device.get_parameters = adev_get_parameters;
3623 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3624 adev->device.open_output_stream = adev_open_output_stream;
3625 adev->device.close_output_stream = adev_close_output_stream;
3626 adev->device.open_input_stream = adev_open_input_stream;
3627 adev->device.close_input_stream = adev_close_input_stream;
3628 adev->device.dump = adev_dump;
3629
3630 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003632 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003633 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003636 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003637 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003638 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3639 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003640 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003641 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003642 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003643 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003644 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303645
3646 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3647 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003649 adev->platform = platform_init(adev);
3650 if (!adev->platform) {
3651 free(adev->snd_dev_ref_cnt);
3652 free(adev);
3653 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3654 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003655 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003656 return -EINVAL;
3657 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003658
Naresh Tanniru4c630392014-05-12 01:05:52 +05303659 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3660
Eric Laurentc4aef752013-09-12 17:45:53 -07003661 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3662 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3663 if (adev->visualizer_lib == NULL) {
3664 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3665 } else {
3666 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3667 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003668 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003669 "visualizer_hal_start_output");
3670 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003671 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003672 "visualizer_hal_stop_output");
3673 }
3674 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003675 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003676 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003677
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003678 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3679 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3680 if (adev->offload_effects_lib == NULL) {
3681 ALOGE("%s: DLOPEN failed for %s", __func__,
3682 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3683 } else {
3684 ALOGV("%s: DLOPEN successful for %s", __func__,
3685 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3686 adev->offload_effects_start_output =
3687 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3688 "offload_effects_bundle_hal_start_output");
3689 adev->offload_effects_stop_output =
3690 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3691 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003692 adev->offload_effects_set_hpx_state =
3693 (int (*)(bool))dlsym(adev->offload_effects_lib,
3694 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003695 }
3696 }
3697
Mingming Yin514a8bc2014-07-29 15:22:21 -07003698 adev->bt_wb_speech_enabled = false;
3699
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003700 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 *device = &adev->device.common;
3702
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003703 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3704 &adev->streams_output_cfg_list);
3705
Kiran Kandi910e1862013-10-29 13:29:42 -07003706 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003707
3708 char value[PROPERTY_VALUE_MAX];
3709 int trial;
3710 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3711 trial = atoi(value);
3712 if (period_size_is_plausible_for_low_latency(trial)) {
3713 pcm_config_low_latency.period_size = trial;
3714 pcm_config_low_latency.start_threshold = trial / 4;
3715 pcm_config_low_latency.avail_min = trial / 4;
3716 configured_low_latency_capture_period_size = trial;
3717 }
3718 }
3719 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3720 trial = atoi(value);
3721 if (period_size_is_plausible_for_low_latency(trial)) {
3722 configured_low_latency_capture_period_size = trial;
3723 }
3724 }
3725
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003726 pthread_mutex_unlock(&adev_init_lock);
3727
Eric Laurent994a6932013-07-17 11:51:42 -07003728 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 return 0;
3730}
3731
3732static struct hw_module_methods_t hal_module_methods = {
3733 .open = adev_open,
3734};
3735
3736struct audio_module HAL_MODULE_INFO_SYM = {
3737 .common = {
3738 .tag = HARDWARE_MODULE_TAG,
3739 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3740 .hal_api_version = HARDWARE_HAL_API_VERSION,
3741 .id = AUDIO_HARDWARE_MODULE_ID,
3742 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003743 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 .methods = &hal_module_methods,
3745 },
3746};