blob: 70ce47137f983fd698f21818feb6970dcbf5540a [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",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
290 format == AUDIO_FORMAT_FLAC)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800291 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700292
293 return false;
294}
295
296static int get_snd_codec_id(audio_format_t format)
297{
298 int id = 0;
299
Ashish Jainf9b78162014-08-25 20:36:25 +0530300 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700301 case AUDIO_FORMAT_MP3:
302 id = SND_AUDIOCODEC_MP3;
303 break;
304 case AUDIO_FORMAT_AAC:
305 id = SND_AUDIOCODEC_AAC;
306 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530307 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800308 id = SND_AUDIOCODEC_PCM;
309 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700310 case AUDIO_FORMAT_FLAC:
311 id = SND_AUDIOCODEC_FLAC;
312 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700313 default:
Mingming Yin90310102013-11-13 16:57:00 -0800314 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700315 }
316
317 return id;
318}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800319
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530320int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530321{
322 int snd_scard_state;
323
324 if (!adev)
325 return SND_CARD_STATE_OFFLINE;
326
327 pthread_mutex_lock(&adev->snd_card_status.lock);
328 snd_scard_state = adev->snd_card_status.state;
329 pthread_mutex_unlock(&adev->snd_card_status.lock);
330
331 return snd_scard_state;
332}
333
334static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
335{
336 if (!adev)
337 return -ENOSYS;
338
339 pthread_mutex_lock(&adev->snd_card_status.lock);
340 adev->snd_card_status.state = snd_scard_state;
341 pthread_mutex_unlock(&adev->snd_card_status.lock);
342
343 return 0;
344}
345
Avinash Vaish71a8b972014-07-24 15:36:33 +0530346static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
347 struct audio_usecase *uc_info)
348{
349 struct listnode *node;
350 struct audio_usecase *usecase;
351
352 if (uc_info == NULL)
353 return -EINVAL;
354
355 /* Re-route all voice usecases on the shared backend other than the
356 specified usecase to new snd devices */
357 list_for_each(node, &adev->usecase_list) {
358 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800359 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530360 enable_audio_route(adev, usecase);
361 }
362 return 0;
363}
364
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700365int pcm_ioctl(struct pcm *pcm, int request, ...)
366{
367 va_list ap;
368 void * arg;
369 int pcm_fd = *(int*)pcm;
370
371 va_start(ap, request);
372 arg = va_arg(ap, void *);
373 va_end(ap);
374
375 return ioctl(pcm_fd, request, arg);
376}
377
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700379 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800380{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700381 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700382 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800383
384 if (usecase == NULL)
385 return -EINVAL;
386
387 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
388
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800389 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700390 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800391 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700392 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800393
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800394#ifdef DS1_DOLBY_DAP_ENABLED
395 audio_extn_dolby_set_dmid(adev);
396 audio_extn_dolby_set_endpoint(adev);
397#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700398 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700399 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530400 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700401 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700402 audio_extn_utils_send_app_type_cfg(usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700404 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700405 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
406 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800407 ALOGV("%s: exit", __func__);
408 return 0;
409}
410
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700411int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700412 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800413{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700414 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700415 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800416
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530417 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800418 return -EINVAL;
419
420 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700421 if (usecase->type == PCM_CAPTURE)
422 snd_device = usecase->in_snd_device;
423 else
424 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800425 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700426 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700427 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
428 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700429 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530430 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431 ALOGV("%s: exit", __func__);
432 return 0;
433}
434
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700435int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700436 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700438 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
439
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800440 if (snd_device < SND_DEVICE_MIN ||
441 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800442 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800443 return -EINVAL;
444 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445
446 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700447
448 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
449 ALOGE("%s: Invalid sound device returned", __func__);
450 return -EINVAL;
451 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700452 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700453 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700454 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700455 return 0;
456 }
457
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700458 if (audio_extn_spkr_prot_is_enabled())
459 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700460 /* start usb playback thread */
461 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
462 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
463 audio_extn_usb_start_playback(adev);
464
465 /* start usb capture thread */
466 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
467 audio_extn_usb_start_capture(adev);
468
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800469 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
470 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700471 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700472 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
473 adev->snd_dev_ref_cnt[snd_device]--;
474 return -EINVAL;
475 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200476 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800477 if (audio_extn_spkr_prot_start_processing(snd_device)) {
478 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200479 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800480 return -EINVAL;
481 }
482 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700483 ALOGV("%s: snd_device(%d: %s)", __func__,
484 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700485 /* due to the possibility of calibration overwrite between listen
486 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700487 audio_extn_sound_trigger_update_device_status(snd_device,
488 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530489 audio_extn_listen_update_device_status(snd_device,
490 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700491 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700493 audio_extn_sound_trigger_update_device_status(snd_device,
494 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530495 audio_extn_listen_update_device_status(snd_device,
496 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700497 return -EINVAL;
498 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300499 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700500 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800501 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800502 return 0;
503}
504
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700505int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700506 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800507{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700508 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
509
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800510 if (snd_device < SND_DEVICE_MIN ||
511 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800512 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800513 return -EINVAL;
514 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700515 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
516 ALOGE("%s: device ref cnt is already 0", __func__);
517 return -EINVAL;
518 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700519
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700520 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700521
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700522 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
523 ALOGE("%s: Invalid sound device returned", __func__);
524 return -EINVAL;
525 }
526
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700527 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700528 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800530 /* exit usb play back thread */
531 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
532 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
533 audio_extn_usb_stop_playback();
534
535 /* exit usb capture thread */
536 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700537 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800538
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800539 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
540 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700541 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700542 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300543 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700544 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300545 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700546
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200547 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700548 audio_extn_sound_trigger_update_device_status(snd_device,
549 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530550 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800551 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700552 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 return 0;
555}
556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700557static void check_usecases_codec_backend(struct audio_device *adev,
558 struct audio_usecase *uc_info,
559 snd_device_t snd_device)
560{
561 struct listnode *node;
562 struct audio_usecase *usecase;
563 bool switch_device[AUDIO_USECASE_MAX];
564 int i, num_uc_to_switch = 0;
565
566 /*
567 * This function is to make sure that all the usecases that are active on
568 * the hardware codec backend are always routed to any one device that is
569 * handled by the hardware codec.
570 * For example, if low-latency and deep-buffer usecases are currently active
571 * on speaker and out_set_parameters(headset) is received on low-latency
572 * output, then we have to make sure deep-buffer is also switched to headset,
573 * because of the limitation that both the devices cannot be enabled
574 * at the same time as they share the same backend.
575 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700576 /*
577 * This call is to check if we need to force routing for a particular stream
578 * If there is a backend configuration change for the device when a
579 * new stream starts, then ADM needs to be closed and re-opened with the new
580 * configuraion. This call check if we need to re-route all the streams
581 * associated with the backend. Touch tone + 24 bit playback.
582 */
583 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 /* Disable all the usecases on the shared backend other than the
586 specified usecase */
587 for (i = 0; i < AUDIO_USECASE_MAX; i++)
588 switch_device[i] = false;
589
590 list_for_each(node, &adev->usecase_list) {
591 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800592 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700594 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
596 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
597 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700598 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700599 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 switch_device[usecase->id] = true;
601 num_uc_to_switch++;
602 }
603 }
604
605 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700606 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530608 /* Make sure the previous devices to be disabled first and then enable the
609 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610 list_for_each(node, &adev->usecase_list) {
611 usecase = node_to_item(node, struct audio_usecase, list);
612 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700613 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 }
615 }
616
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
619 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700620 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700621 }
622 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700624 /* Re-route all the usecases on the shared backend other than the
625 specified usecase to new snd devices */
626 list_for_each(node, &adev->usecase_list) {
627 usecase = node_to_item(node, struct audio_usecase, list);
628 /* Update the out_snd_device only before enabling the audio route */
629 if (switch_device[usecase->id] ) {
630 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800631 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530632 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 }
634 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635 }
636}
637
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700638static void check_and_route_capture_usecases(struct audio_device *adev,
639 struct audio_usecase *uc_info,
640 snd_device_t snd_device)
641{
642 struct listnode *node;
643 struct audio_usecase *usecase;
644 bool switch_device[AUDIO_USECASE_MAX];
645 int i, num_uc_to_switch = 0;
646
647 /*
648 * This function is to make sure that all the active capture usecases
649 * are always routed to the same input sound device.
650 * For example, if audio-record and voice-call usecases are currently
651 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
652 * is received for voice call then we have to make sure that audio-record
653 * usecase is also switched to earpiece i.e. voice-dmic-ef,
654 * because of the limitation that two devices cannot be enabled
655 * at the same time if they share the same backend.
656 */
657 for (i = 0; i < AUDIO_USECASE_MAX; i++)
658 switch_device[i] = false;
659
660 list_for_each(node, &adev->usecase_list) {
661 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800662 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700663 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700664 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530665 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700666 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700667 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
668 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700669 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700670 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700671 switch_device[usecase->id] = true;
672 num_uc_to_switch++;
673 }
674 }
675
676 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700677 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700678
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530679 /* Make sure the previous devices to be disabled first and then enable the
680 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700681 list_for_each(node, &adev->usecase_list) {
682 usecase = node_to_item(node, struct audio_usecase, list);
683 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700684 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800685 }
686 }
687
688 list_for_each(node, &adev->usecase_list) {
689 usecase = node_to_item(node, struct audio_usecase, list);
690 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700691 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700692 }
693 }
694
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 /* Re-route all the usecases on the shared backend other than the
696 specified usecase to new snd devices */
697 list_for_each(node, &adev->usecase_list) {
698 usecase = node_to_item(node, struct audio_usecase, list);
699 /* Update the in_snd_device only before enabling the audio route */
700 if (switch_device[usecase->id] ) {
701 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800702 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530703 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 }
705 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700706 }
707}
708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700710static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800711{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700712 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700713 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800714
715 switch (channels) {
716 /*
717 * Do not handle stereo output in Multi-channel cases
718 * Stereo case is handled in normal playback path
719 */
720 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700721 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
722 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
723 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
724 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
725 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
726 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800727 break;
728 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700729 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
730 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
731 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
732 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
733 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
734 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
735 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736 break;
737 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700738 ALOGE("HDMI does not support multi channel playback");
739 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800740 break;
741 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700742 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743}
744
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700745static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
746{
747 struct audio_usecase *usecase;
748 struct listnode *node;
749
750 list_for_each(node, &adev->usecase_list) {
751 usecase = node_to_item(node, struct audio_usecase, list);
752 if (usecase->type == VOICE_CALL) {
753 ALOGV("%s: usecase id %d", __func__, usecase->id);
754 return usecase->id;
755 }
756 }
757 return USECASE_INVALID;
758}
759
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700760struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700761 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762{
763 struct audio_usecase *usecase;
764 struct listnode *node;
765
766 list_for_each(node, &adev->usecase_list) {
767 usecase = node_to_item(node, struct audio_usecase, list);
768 if (usecase->id == uc_id)
769 return usecase;
770 }
771 return NULL;
772}
773
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700774int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800776 snd_device_t out_snd_device = SND_DEVICE_NONE;
777 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700778 struct audio_usecase *usecase = NULL;
779 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800780 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800781 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800782 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800783 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800785
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700786 usecase = get_usecase_from_list(adev, uc_id);
787 if (usecase == NULL) {
788 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
789 return -EINVAL;
790 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800791
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800792 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800793 (usecase->type == VOIP_CALL) ||
794 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700795 out_snd_device = platform_get_output_snd_device(adev->platform,
796 usecase->stream.out->devices);
797 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700798 usecase->devices = usecase->stream.out->devices;
799 } else {
800 /*
801 * If the voice call is active, use the sound devices of voice call usecase
802 * so that it would not result any device switch. All the usecases will
803 * be switched to new device when select_devices() is called for voice call
804 * usecase. This is to avoid switching devices for voice call when
805 * check_usecases_codec_backend() is called below.
806 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700807 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700808 vc_usecase = get_usecase_from_list(adev,
809 get_voice_usecase_id_from_list(adev));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700810 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
811 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 in_snd_device = vc_usecase->in_snd_device;
813 out_snd_device = vc_usecase->out_snd_device;
814 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800815 } else if (voice_extn_compress_voip_is_active(adev)) {
816 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700817 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530818 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700819 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800820 in_snd_device = voip_usecase->in_snd_device;
821 out_snd_device = voip_usecase->out_snd_device;
822 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800823 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800824 hfp_ucid = audio_extn_hfp_get_usecase();
825 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700826 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800827 in_snd_device = hfp_usecase->in_snd_device;
828 out_snd_device = hfp_usecase->out_snd_device;
829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 }
831 if (usecase->type == PCM_PLAYBACK) {
832 usecase->devices = usecase->stream.out->devices;
833 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700834 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700835 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700837 if (usecase->stream.out == adev->primary_output &&
838 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800839 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
840 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700841 select_devices(adev, adev->active_input->usecase);
842 }
843 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700844 } else if (usecase->type == PCM_CAPTURE) {
845 usecase->devices = usecase->stream.in->device;
846 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700847 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700848 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530849 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
850 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
851 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
852 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700853 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800854 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700855 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
856 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700857 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700858 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700859 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 }
861 }
862
863 if (out_snd_device == usecase->out_snd_device &&
864 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800865 return 0;
866 }
867
sangwoobc677242013-08-08 16:53:43 +0900868 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 out_snd_device, platform_get_snd_device_name(out_snd_device),
870 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800872 /*
873 * Limitation: While in call, to do a device switch we need to disable
874 * and enable both RX and TX devices though one of them is same as current
875 * device.
876 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700877 if ((usecase->type == VOICE_CALL) &&
878 (usecase->in_snd_device != SND_DEVICE_NONE) &&
879 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700880 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800881 }
882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 /* Disable current sound devices */
884 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700885 disable_audio_route(adev, usecase);
886 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800887 }
888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700890 disable_audio_route(adev, usecase);
891 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800892 }
893
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800894 /* Applicable only on the targets that has external modem.
895 * New device information should be sent to modem before enabling
896 * the devices to reduce in-call device switch time.
897 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700898 if ((usecase->type == VOICE_CALL) &&
899 (usecase->in_snd_device != SND_DEVICE_NONE) &&
900 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800901 status = platform_switch_voice_call_enable_device_config(adev->platform,
902 out_snd_device,
903 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700904 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800905
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 /* Enable new sound devices */
907 if (out_snd_device != SND_DEVICE_NONE) {
908 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
909 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700910 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800911 }
912
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700913 if (in_snd_device != SND_DEVICE_NONE) {
914 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700915 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700916 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917
Avinash Vaish71a8b972014-07-24 15:36:33 +0530918 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700919 status = platform_switch_voice_call_device_post(adev->platform,
920 out_snd_device,
921 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530922 enable_audio_route_for_voice_usecases(adev, usecase);
923 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800924
sangwoo170731f2013-06-08 15:36:36 +0900925 usecase->in_snd_device = in_snd_device;
926 usecase->out_snd_device = out_snd_device;
927
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530928 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700929 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530930 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700931 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530932 usecase->stream.out->flags,
933 usecase->stream.out->format,
934 usecase->stream.out->sample_rate,
935 usecase->stream.out->bit_width,
936 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700937 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530938 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700939
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700940 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900941
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800942 /* Applicable only on the targets that has external modem.
943 * Enable device command should be sent to modem only after
944 * enabling voice call mixer controls
945 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700946 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800947 status = platform_switch_voice_call_usecase_route_post(adev->platform,
948 out_snd_device,
949 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530950 ALOGD("%s: done",__func__);
951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 return status;
953}
954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955static int stop_input_stream(struct stream_in *in)
956{
957 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958 struct audio_usecase *uc_info;
959 struct audio_device *adev = in->dev;
960
Eric Laurentc8400632013-02-14 19:04:54 -0800961 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962
Eric Laurent994a6932013-07-17 11:51:42 -0700963 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700964 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965 uc_info = get_usecase_from_list(adev, in->usecase);
966 if (uc_info == NULL) {
967 ALOGE("%s: Could not find the usecase (%d) in the list",
968 __func__, in->usecase);
969 return -EINVAL;
970 }
971
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800972 /* Close in-call recording streams */
973 voice_check_and_stop_incall_rec_usecase(adev, in);
974
Eric Laurent150dbfe2013-02-27 14:31:02 -0800975 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700976 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977
978 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700979 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800981 list_remove(&uc_info->list);
982 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983
Eric Laurent994a6932013-07-17 11:51:42 -0700984 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 return ret;
986}
987
988int start_input_stream(struct stream_in *in)
989{
990 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800991 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 struct audio_usecase *uc_info;
993 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +0530994 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995
Mingming Yine62d7842013-10-25 16:26:03 -0700996 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530997 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
998 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700999
Naresh Tanniru80659832014-06-04 18:17:56 +05301000
1001 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301002 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301003 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301004 goto error_config;
1005 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301006
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001007 /* Check if source matches incall recording usecase criteria */
1008 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1009 if (ret)
1010 goto error_config;
1011 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001012 ALOGD("%s: Updated usecase(%d: %s)",
1013 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001014
Eric Laurentb23d5282013-05-14 15:27:20 -07001015 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016 if (in->pcm_device_id < 0) {
1017 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1018 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001019 ret = -EINVAL;
1020 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022
1023 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001025
1026 if (!uc_info) {
1027 ret = -ENOMEM;
1028 goto error_config;
1029 }
1030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 uc_info->id = in->usecase;
1032 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001033 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001034 uc_info->devices = in->device;
1035 uc_info->in_snd_device = SND_DEVICE_NONE;
1036 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001038 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301039 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001040 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041
Eric Laurentc8400632013-02-14 19:04:54 -08001042 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001043 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1044
1045 unsigned int flags = PCM_IN;
1046 unsigned int pcm_open_retry_count = 0;
1047
1048 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1049 flags |= PCM_MMAP | PCM_NOIRQ;
1050 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1051 }
1052
1053 while (1) {
1054 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1055 flags, &in->config);
1056 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1057 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1058 if (in->pcm != NULL) {
1059 pcm_close(in->pcm);
1060 in->pcm = NULL;
1061 }
1062 if (pcm_open_retry_count-- == 0) {
1063 ret = -EIO;
1064 goto error_open;
1065 }
1066 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1067 continue;
1068 }
1069 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301071 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301072
Eric Laurent994a6932013-07-17 11:51:42 -07001073 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001074 return ret;
1075
1076error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301078 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001079
1080error_config:
1081 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001083
1084 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085}
1086
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001087/* must be called with out->lock locked */
1088static int send_offload_cmd_l(struct stream_out* out, int command)
1089{
1090 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1091
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001092 if (!cmd) {
1093 ALOGE("failed to allocate mem for command 0x%x", command);
1094 return -ENOMEM;
1095 }
1096
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001097 ALOGVV("%s %d", __func__, command);
1098
1099 cmd->cmd = command;
1100 list_add_tail(&out->offload_cmd_list, &cmd->node);
1101 pthread_cond_signal(&out->offload_cond);
1102 return 0;
1103}
1104
1105/* must be called iwth out->lock locked */
1106static void stop_compressed_output_l(struct stream_out *out)
1107{
1108 out->offload_state = OFFLOAD_STATE_IDLE;
1109 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001110 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001111 if (out->compr != NULL) {
1112 compress_stop(out->compr);
1113 while (out->offload_thread_blocked) {
1114 pthread_cond_wait(&out->cond, &out->lock);
1115 }
1116 }
1117}
1118
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001119bool is_offload_usecase(audio_usecase_t uc_id)
1120{
1121 unsigned int i;
1122 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1123 if (uc_id == offload_usecases[i])
1124 return true;
1125 }
1126 return false;
1127}
1128
1129static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1130{
1131 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1132 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1133 char value[PROPERTY_VALUE_MAX] = {0};
1134
1135 property_get("audio.offload.multiple.enabled", value, NULL);
1136 if (!(atoi(value) || !strncmp("true", value, 4)))
1137 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1138
1139 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1140 for (i = 0; i < num_usecase; i++) {
1141 if (!(adev->offload_usecases_state & (0x1<<i))) {
1142 adev->offload_usecases_state |= 0x1 << i;
1143 ret = offload_usecases[i];
1144 break;
1145 }
1146 }
1147 ALOGV("%s: offload usecase is %d", __func__, ret);
1148 return ret;
1149}
1150
1151static void free_offload_usecase(struct audio_device *adev,
1152 audio_usecase_t uc_id)
1153{
1154 unsigned int i;
1155 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1156 if (offload_usecases[i] == uc_id) {
1157 adev->offload_usecases_state &= ~(0x1<<i);
1158 break;
1159 }
1160 }
1161 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1162}
1163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001164static void *offload_thread_loop(void *context)
1165{
1166 struct stream_out *out = (struct stream_out *) context;
1167 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001168 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001169
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001170 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1171 set_sched_policy(0, SP_FOREGROUND);
1172 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1173
1174 ALOGV("%s", __func__);
1175 pthread_mutex_lock(&out->lock);
1176 for (;;) {
1177 struct offload_cmd *cmd = NULL;
1178 stream_callback_event_t event;
1179 bool send_callback = false;
1180
1181 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1182 __func__, list_empty(&out->offload_cmd_list),
1183 out->offload_state);
1184 if (list_empty(&out->offload_cmd_list)) {
1185 ALOGV("%s SLEEPING", __func__);
1186 pthread_cond_wait(&out->offload_cond, &out->lock);
1187 ALOGV("%s RUNNING", __func__);
1188 continue;
1189 }
1190
1191 item = list_head(&out->offload_cmd_list);
1192 cmd = node_to_item(item, struct offload_cmd, node);
1193 list_remove(item);
1194
1195 ALOGVV("%s STATE %d CMD %d out->compr %p",
1196 __func__, out->offload_state, cmd->cmd, out->compr);
1197
1198 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1199 free(cmd);
1200 break;
1201 }
1202
1203 if (out->compr == NULL) {
1204 ALOGE("%s: Compress handle is NULL", __func__);
1205 pthread_cond_signal(&out->cond);
1206 continue;
1207 }
1208 out->offload_thread_blocked = true;
1209 pthread_mutex_unlock(&out->lock);
1210 send_callback = false;
1211 switch(cmd->cmd) {
1212 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001213 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001214 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001215 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001216 send_callback = true;
1217 event = STREAM_CBK_EVENT_WRITE_READY;
1218 break;
1219 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001220 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301221 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001222 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301223 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001224 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301225 if (ret < 0)
1226 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301227 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301228 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001229 compress_drain(out->compr);
1230 else
1231 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301232 if (ret != -ENETRESET) {
1233 send_callback = true;
1234 event = STREAM_CBK_EVENT_DRAIN_READY;
1235 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1236 } else
1237 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001238 break;
1239 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001240 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001241 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001242 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001243 send_callback = true;
1244 event = STREAM_CBK_EVENT_DRAIN_READY;
1245 break;
1246 default:
1247 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1248 break;
1249 }
1250 pthread_mutex_lock(&out->lock);
1251 out->offload_thread_blocked = false;
1252 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001253 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001254 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001255 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001256 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001257 free(cmd);
1258 }
1259
1260 pthread_cond_signal(&out->cond);
1261 while (!list_empty(&out->offload_cmd_list)) {
1262 item = list_head(&out->offload_cmd_list);
1263 list_remove(item);
1264 free(node_to_item(item, struct offload_cmd, node));
1265 }
1266 pthread_mutex_unlock(&out->lock);
1267
1268 return NULL;
1269}
1270
1271static int create_offload_callback_thread(struct stream_out *out)
1272{
1273 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1274 list_init(&out->offload_cmd_list);
1275 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1276 offload_thread_loop, out);
1277 return 0;
1278}
1279
1280static int destroy_offload_callback_thread(struct stream_out *out)
1281{
1282 pthread_mutex_lock(&out->lock);
1283 stop_compressed_output_l(out);
1284 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1285
1286 pthread_mutex_unlock(&out->lock);
1287 pthread_join(out->offload_thread, (void **) NULL);
1288 pthread_cond_destroy(&out->offload_cond);
1289
1290 return 0;
1291}
1292
Eric Laurent07eeafd2013-10-06 12:52:49 -07001293static bool allow_hdmi_channel_config(struct audio_device *adev)
1294{
1295 struct listnode *node;
1296 struct audio_usecase *usecase;
1297 bool ret = true;
1298
1299 list_for_each(node, &adev->usecase_list) {
1300 usecase = node_to_item(node, struct audio_usecase, list);
1301 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1302 /*
1303 * If voice call is already existing, do not proceed further to avoid
1304 * disabling/enabling both RX and TX devices, CSD calls, etc.
1305 * Once the voice call done, the HDMI channels can be configured to
1306 * max channels of remaining use cases.
1307 */
1308 if (usecase->id == USECASE_VOICE_CALL) {
1309 ALOGD("%s: voice call is active, no change in HDMI channels",
1310 __func__);
1311 ret = false;
1312 break;
1313 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1314 ALOGD("%s: multi channel playback is active, "
1315 "no change in HDMI channels", __func__);
1316 ret = false;
1317 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001318 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001319 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001320 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1321 ", no change in HDMI channels", __func__,
1322 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001323 ret = false;
1324 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001325 }
1326 }
1327 }
1328 return ret;
1329}
1330
1331static int check_and_set_hdmi_channels(struct audio_device *adev,
1332 unsigned int channels)
1333{
1334 struct listnode *node;
1335 struct audio_usecase *usecase;
1336
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001337 unsigned int supported_channels = platform_edid_get_max_channels(
1338 adev->platform);
1339 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001340 /* Check if change in HDMI channel config is allowed */
1341 if (!allow_hdmi_channel_config(adev))
1342 return 0;
1343
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001344 if (channels > supported_channels)
1345 channels = supported_channels;
1346
Eric Laurent07eeafd2013-10-06 12:52:49 -07001347 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001348 ALOGD("%s: Requested channels are same as current channels(%d)",
1349 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001350 return 0;
1351 }
1352
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001353 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001354 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001355 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001356 adev->cur_hdmi_channels = channels;
1357
1358 /*
1359 * Deroute all the playback streams routed to HDMI so that
1360 * the back end is deactivated. Note that backend will not
1361 * be deactivated if any one stream is connected to it.
1362 */
1363 list_for_each(node, &adev->usecase_list) {
1364 usecase = node_to_item(node, struct audio_usecase, list);
1365 if (usecase->type == PCM_PLAYBACK &&
1366 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001367 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001368 }
1369 }
1370
1371 /*
1372 * Enable all the streams disabled above. Now the HDMI backend
1373 * will be activated with new channel configuration
1374 */
1375 list_for_each(node, &adev->usecase_list) {
1376 usecase = node_to_item(node, struct audio_usecase, list);
1377 if (usecase->type == PCM_PLAYBACK &&
1378 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001379 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001380 }
1381 }
1382
1383 return 0;
1384}
1385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001386static int stop_output_stream(struct stream_out *out)
1387{
1388 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001389 struct audio_usecase *uc_info;
1390 struct audio_device *adev = out->dev;
1391
Eric Laurent994a6932013-07-17 11:51:42 -07001392 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394 uc_info = get_usecase_from_list(adev, out->usecase);
1395 if (uc_info == NULL) {
1396 ALOGE("%s: Could not find the usecase (%d) in the list",
1397 __func__, out->usecase);
1398 return -EINVAL;
1399 }
1400
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001401 if (is_offload_usecase(out->usecase) &&
1402 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001403 if (adev->visualizer_stop_output != NULL)
1404 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001405
1406 audio_extn_dts_remove_state_notifier_node(out->usecase);
1407
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001408 if (adev->offload_effects_stop_output != NULL)
1409 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1410 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001411
Eric Laurent150dbfe2013-02-27 14:31:02 -08001412 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001413 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414
1415 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001416 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001418 list_remove(&uc_info->list);
1419 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001421 if (is_offload_usecase(out->usecase) &&
1422 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1423 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1424 ALOGV("Disable passthrough , reset mixer to pcm");
1425 /* NO_PASSTHROUGH */
1426 out->compr_config.codec->compr_passthr = 0;
1427 audio_extn_dolby_set_hdmi_config(adev, out);
1428 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1429 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001430 /* Must be called after removing the usecase from list */
1431 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1432 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1433
Eric Laurent994a6932013-07-17 11:51:42 -07001434 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435 return ret;
1436}
1437
1438int start_output_stream(struct stream_out *out)
1439{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001441 int sink_channels = 0;
1442 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 struct audio_usecase *uc_info;
1444 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301445 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001447 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1448 ret = -EINVAL;
1449 goto error_config;
1450 }
1451
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301452 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1453 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1454 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301455
Naresh Tanniru80659832014-06-04 18:17:56 +05301456 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301457 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301458 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301459 goto error_config;
1460 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301461
Eric Laurentb23d5282013-05-14 15:27:20 -07001462 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 if (out->pcm_device_id < 0) {
1464 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1465 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001466 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001467 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468 }
1469
1470 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001471
1472 if (!uc_info) {
1473 ret = -ENOMEM;
1474 goto error_config;
1475 }
1476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477 uc_info->id = out->usecase;
1478 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001479 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001480 uc_info->devices = out->devices;
1481 uc_info->in_snd_device = SND_DEVICE_NONE;
1482 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001483 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001484 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001485 if (is_offload_usecase(out->usecase)) {
1486 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001487 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1488 }
1489 }
Mingming Yin9c041392014-05-01 15:37:31 -07001490 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1491 if (!strncmp("true", prop_value, 4)) {
1492 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001493 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1494 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001495 check_and_set_hdmi_channels(adev, sink_channels);
1496 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001497 if (is_offload_usecase(out->usecase)) {
1498 unsigned int ch_count = out->compr_config.codec->ch_in;
1499 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1500 /* backend channel config for passthrough stream is stereo */
1501 ch_count = 2;
1502 check_and_set_hdmi_channels(adev, ch_count);
1503 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001504 check_and_set_hdmi_channels(adev, out->config.channels);
1505 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001506 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001507 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001508 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001510 select_devices(adev, out->usecase);
1511
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001512 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1513 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001514 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001515 unsigned int flags = PCM_OUT;
1516 unsigned int pcm_open_retry_count = 0;
1517 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1518 flags |= PCM_MMAP | PCM_NOIRQ;
1519 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1520 } else
1521 flags |= PCM_MONOTONIC;
1522
1523 while (1) {
1524 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1525 flags, &out->config);
1526 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1527 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1528 if (out->pcm != NULL) {
1529 pcm_close(out->pcm);
1530 out->pcm = NULL;
1531 }
1532 if (pcm_open_retry_count-- == 0) {
1533 ret = -EIO;
1534 goto error_open;
1535 }
1536 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1537 continue;
1538 }
1539 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001540 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001541 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1542 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001543 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001544 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1545 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001547 out->compr = compress_open(adev->snd_card,
1548 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001549 COMPRESS_IN, &out->compr_config);
1550 if (out->compr && !is_compress_ready(out->compr)) {
1551 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1552 compress_close(out->compr);
1553 out->compr = NULL;
1554 ret = -EIO;
1555 goto error_open;
1556 }
1557 if (out->offload_callback)
1558 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001559
Fred Oh3f43e742015-03-04 18:42:34 -08001560 /* Since small bufs uses blocking writes, a write will be blocked
1561 for the default max poll time (20s) in the event of an SSR.
1562 Reduce the poll time to observe and deal with SSR faster.
1563 */
1564 if (out->use_small_bufs) {
1565 compress_set_max_poll_wait(out->compr, 1000);
1566 }
1567
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001568 audio_extn_dts_create_state_notifier_node(out->usecase);
1569 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1570 popcount(out->channel_mask),
1571 out->playback_started);
1572
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001573#ifdef DS1_DOLBY_DDP_ENABLED
1574 if (audio_extn_is_dolby_format(out->format))
1575 audio_extn_dolby_send_ddp_endp_params(adev);
1576#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001577 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1578 if (adev->visualizer_start_output != NULL)
1579 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1580 if (adev->offload_effects_start_output != NULL)
1581 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001582 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001583 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 }
Eric Laurent994a6932013-07-17 11:51:42 -07001585 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001587error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001589error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001590 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591}
1592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593static int check_input_parameters(uint32_t sample_rate,
1594 audio_format_t format,
1595 int channel_count)
1596{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001597 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001599 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001600 !voice_extn_compress_voip_is_format_supported(format) &&
1601 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001602
1603 switch (channel_count) {
1604 case 1:
1605 case 2:
1606 case 6:
1607 break;
1608 default:
1609 ret = -EINVAL;
1610 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611
1612 switch (sample_rate) {
1613 case 8000:
1614 case 11025:
1615 case 12000:
1616 case 16000:
1617 case 22050:
1618 case 24000:
1619 case 32000:
1620 case 44100:
1621 case 48000:
1622 break;
1623 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001624 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625 }
1626
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001627 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001628}
1629
1630static size_t get_input_buffer_size(uint32_t sample_rate,
1631 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001632 int channel_count,
1633 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634{
1635 size_t size = 0;
1636
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001637 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1638 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001640 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001641 if (is_low_latency)
1642 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001643 /* ToDo: should use frame_size computed based on the format and
1644 channel_count here. */
1645 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001647 /* make sure the size is multiple of 32 bytes
1648 * At 48 kHz mono 16-bit PCM:
1649 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1650 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1651 */
1652 size += 0x1f;
1653 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001654
1655 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656}
1657
1658static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1659{
1660 struct stream_out *out = (struct stream_out *)stream;
1661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001662 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663}
1664
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001665static int out_set_sample_rate(struct audio_stream *stream __unused,
1666 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667{
1668 return -ENOSYS;
1669}
1670
1671static size_t out_get_buffer_size(const struct audio_stream *stream)
1672{
1673 struct stream_out *out = (struct stream_out *)stream;
1674
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001675 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001676 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001677 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1678 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001680 return out->config.period_size *
1681 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682}
1683
1684static uint32_t out_get_channels(const struct audio_stream *stream)
1685{
1686 struct stream_out *out = (struct stream_out *)stream;
1687
1688 return out->channel_mask;
1689}
1690
1691static audio_format_t out_get_format(const struct audio_stream *stream)
1692{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001693 struct stream_out *out = (struct stream_out *)stream;
1694
1695 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696}
1697
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001698static int out_set_format(struct audio_stream *stream __unused,
1699 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700{
1701 return -ENOSYS;
1702}
1703
1704static int out_standby(struct audio_stream *stream)
1705{
1706 struct stream_out *out = (struct stream_out *)stream;
1707 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301709 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1710 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001711 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1712 /* Ignore standby in case of voip call because the voip output
1713 * stream is closed in adev_close_output_stream()
1714 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301715 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001716 return 0;
1717 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001721 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001723 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724 if (out->pcm) {
1725 pcm_close(out->pcm);
1726 out->pcm = NULL;
1727 }
1728 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001729 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001731 out->gapless_mdata.encoder_delay = 0;
1732 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 if (out->compr != NULL) {
1734 compress_close(out->compr);
1735 out->compr = NULL;
1736 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001737 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001739 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 }
1741 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001742 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 return 0;
1744}
1745
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001746static int out_dump(const struct audio_stream *stream __unused,
1747 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748{
1749 return 0;
1750}
1751
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001752static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1753{
1754 int ret = 0;
1755 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001756 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001757 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001758 tmp_mdata.encoder_delay = 0;
1759 tmp_mdata.encoder_padding = 0;
Amit Shekharcbf04982015-01-20 20:19:31 -08001760 tmp_mdata.min_blk_size = 0;
1761 tmp_mdata.max_blk_size = 0;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001762
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001763 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001764 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001765 return -EINVAL;
1766 }
1767
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001768 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1769 if (ret >= 0) {
1770 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1771 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1772 ALOGV("ADTS format is set in offload mode");
1773 }
1774 out->send_new_metadata = 1;
1775 }
1776
Mingming Yin3ee55c62014-08-04 14:23:35 -07001777 if (out->format == AUDIO_FORMAT_FLAC) {
1778 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1779 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001780 tmp_mdata.min_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001781 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1782 out->send_new_metadata = 1;
1783 }
1784 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1785 if (ret >= 0) {
Amit Shekharcbf04982015-01-20 20:19:31 -08001786 tmp_mdata.max_blk_size =
Mingming Yin3ee55c62014-08-04 14:23:35 -07001787 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1788 out->send_new_metadata = 1;
1789 }
1790 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1791 if (ret >= 0) {
1792 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1793 out->send_new_metadata = 1;
1794 }
1795 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1796 if (ret >= 0) {
1797 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1798 out->send_new_metadata = 1;
1799 }
1800 }
1801
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001802 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1803 if(ret >= 0)
1804 is_meta_data_params = true;
1805 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1806 if(ret >= 0 )
1807 is_meta_data_params = true;
1808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1809 if(ret >= 0 )
1810 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1812 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001813 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001814 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001815 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001816 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1817 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001818 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001819 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001820 }
1821
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001822 if(!is_meta_data_params) {
1823 ALOGV("%s: Not gapless meta data params", __func__);
1824 return 0;
1825 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826 out->gapless_mdata = tmp_mdata;
1827 out->send_new_metadata = 1;
1828 ALOGV("%s new encoder delay %u and padding %u", __func__,
1829 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1830
1831 return 0;
1832}
1833
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001834static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1835{
1836 return out == adev->primary_output || out == adev->voice_tx_output;
1837}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1840{
1841 struct stream_out *out = (struct stream_out *)stream;
1842 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001843 struct audio_usecase *usecase;
1844 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 struct str_parms *parms;
1846 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001847 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001848 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849
sangwoobc677242013-08-08 16:53:43 +09001850 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301853 if (!parms)
1854 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001855 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1856 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001859 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001861 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301862 * When HDMI cable is unplugged/usb hs is disconnected the
1863 * music playback is paused and the policy manager sends routing=0
1864 * But the audioflingercontinues to write data until standby time
1865 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001866 * Avoid this by routing audio to speaker until standby.
1867 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301868 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1869 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001871 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1872 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 }
1874
1875 /*
1876 * select_devices() call below switches all the usecases on the same
1877 * backend to the new device. Refer to check_usecases_codec_backend() in
1878 * the select_devices(). But how do we undo this?
1879 *
1880 * For example, music playback is active on headset (deep-buffer usecase)
1881 * and if we go to ringtones and select a ringtone, low-latency usecase
1882 * will be started on headset+speaker. As we can't enable headset+speaker
1883 * and headset devices at the same time, select_devices() switches the music
1884 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1885 * So when the ringtone playback is completed, how do we undo the same?
1886 *
1887 * We are relying on the out_set_parameters() call on deep-buffer output,
1888 * once the ringtone playback is ended.
1889 * NOTE: We should not check if the current devices are same as new devices.
1890 * Because select_devices() must be called to switch back the music
1891 * playback to headset.
1892 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001893 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 out->devices = val;
1895
1896 if (!out->standby)
1897 select_devices(adev, out->usecase);
1898
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001899 if (output_drives_call(adev, out)) {
1900 if(!voice_is_in_call(adev)) {
1901 if (adev->mode == AUDIO_MODE_IN_CALL) {
1902 adev->current_call_output = out;
1903 ret = voice_start_call(adev);
1904 }
1905 } else {
1906 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001907 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001908 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001909 }
1910 }
1911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001913 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001915
1916 if (out == adev->primary_output) {
1917 pthread_mutex_lock(&adev->lock);
1918 audio_extn_set_parameters(adev, parms);
1919 pthread_mutex_unlock(&adev->lock);
1920 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001921 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001922 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001923 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001924
1925 audio_extn_dts_create_state_notifier_node(out->usecase);
1926 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1927 popcount(out->channel_mask),
1928 out->playback_started);
1929
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001930 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001931 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001933 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301934error:
Eric Laurent994a6932013-07-17 11:51:42 -07001935 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 return ret;
1937}
1938
1939static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1940{
1941 struct stream_out *out = (struct stream_out *)stream;
1942 struct str_parms *query = str_parms_create_str(keys);
1943 char *str;
1944 char value[256];
1945 struct str_parms *reply = str_parms_create();
1946 size_t i, j;
1947 int ret;
1948 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001949
1950 if (!query || !reply) {
1951 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1952 return NULL;
1953 }
1954
Eric Laurent994a6932013-07-17 11:51:42 -07001955 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1957 if (ret >= 0) {
1958 value[0] = '\0';
1959 i = 0;
1960 while (out->supported_channel_masks[i] != 0) {
1961 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1962 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1963 if (!first) {
1964 strcat(value, "|");
1965 }
1966 strcat(value, out_channels_name_to_enum_table[j].name);
1967 first = false;
1968 break;
1969 }
1970 }
1971 i++;
1972 }
1973 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1974 str = str_parms_to_str(reply);
1975 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001976 voice_extn_out_get_parameters(out, query, reply);
1977 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001978 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001979 free(str);
1980 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001983
1984 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1985 if (ret >= 0) {
1986 value[0] = '\0';
1987 i = 0;
1988 first = true;
1989 while (out->supported_formats[i] != 0) {
1990 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1991 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1992 if (!first) {
1993 strcat(value, "|");
1994 }
1995 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1996 first = false;
1997 break;
1998 }
1999 }
2000 i++;
2001 }
2002 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2003 str = str_parms_to_str(reply);
2004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 str_parms_destroy(query);
2006 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002007 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008 return str;
2009}
2010
2011static uint32_t out_get_latency(const struct audio_stream_out *stream)
2012{
2013 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002014 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015
Alexy Josephaa54c872014-12-03 02:46:47 -08002016 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002017 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002018 } else {
2019 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002021 }
2022
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302023 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002024 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025}
2026
2027static int out_set_volume(struct audio_stream_out *stream, float left,
2028 float right)
2029{
Eric Laurenta9024de2013-04-04 09:19:12 -07002030 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 int volume[2];
2032
Eric Laurenta9024de2013-04-04 09:19:12 -07002033 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2034 /* only take left channel into account: the API is for stereo anyway */
2035 out->muted = (left == 0.0f);
2036 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002037 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002038 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2039 /*
2040 * Set mute or umute on HDMI passthrough stream.
2041 * Only take left channel into account.
2042 * Mute is 0 and unmute 1
2043 */
2044 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2045 } else {
2046 char mixer_ctl_name[128];
2047 struct audio_device *adev = out->dev;
2048 struct mixer_ctl *ctl;
2049 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002050 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002052 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2053 "Compress Playback %d Volume", pcm_device_id);
2054 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2055 if (!ctl) {
2056 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2057 __func__, mixer_ctl_name);
2058 return -EINVAL;
2059 }
2060 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2061 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2062 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2063 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002065 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067 return -ENOSYS;
2068}
2069
2070static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2071 size_t bytes)
2072{
2073 struct stream_out *out = (struct stream_out *)stream;
2074 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302075 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002076 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302079
Naresh Tanniru80659832014-06-04 18:17:56 +05302080 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002081 // increase written size during SSR to avoid mismatch
2082 // with the written frames count in AF
2083 if (!is_offload_usecase(out->usecase))
2084 out->written += bytes / (out->config.channels * sizeof(short));
2085
Naresh Tanniru80659832014-06-04 18:17:56 +05302086 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302087 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302088 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302089 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002090 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302091 //during SSR for compress usecase we should return error to flinger
2092 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2093 pthread_mutex_unlock(&out->lock);
2094 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302095 }
2096 }
2097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002099 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002100 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002101 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2102 ret = voice_extn_compress_voip_start_output_stream(out);
2103 else
2104 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002105 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002108 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 goto exit;
2110 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002113 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002114 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002115 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002116 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002117 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2118 out->send_new_metadata = 0;
2119 }
2120
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302122 if (ret < 0)
2123 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002125 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302126 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302128 } else if (-ENETRESET == ret) {
2129 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2130 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2131 pthread_mutex_unlock(&out->lock);
2132 out_standby(&out->stream.common);
2133 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302135 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 compress_start(out->compr);
2137 out->playback_started = 1;
2138 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002139
2140 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2141 popcount(out->channel_mask),
2142 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 }
2144 pthread_mutex_unlock(&out->lock);
2145 return ret;
2146 } else {
2147 if (out->pcm) {
2148 if (out->muted)
2149 memset((void *)buffer, 0, bytes);
2150 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002151 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2152 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2153 else
2154 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302155 if (ret < 0)
2156 ret = -errno;
2157 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002158 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 }
2161
2162exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302163 /* ToDo: There may be a corner case when SSR happens back to back during
2164 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302165 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302166 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302167 }
2168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 pthread_mutex_unlock(&out->lock);
2170
2171 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002172 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002173 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302174 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302175 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302176 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302177 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302178 out->standby = true;
2179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002181 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302182 out_get_sample_rate(&out->stream.common));
2183
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184 }
2185 return bytes;
2186}
2187
2188static int out_get_render_position(const struct audio_stream_out *stream,
2189 uint32_t *dsp_frames)
2190{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302192 struct audio_device *adev = out->dev;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002193 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002194 ssize_t ret = 0;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002195 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 pthread_mutex_lock(&out->lock);
2197 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302198 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302200 if (ret < 0)
2201 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 ALOGVV("%s rendered frames %d sample_rate %d",
2203 __func__, *dsp_frames, out->sample_rate);
2204 }
2205 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302206 if (-ENETRESET == ret) {
2207 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2208 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2209 return -EINVAL;
2210 } else if(ret < 0) {
2211 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2212 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302213 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2214 /*
2215 * Handle corner case where compress session is closed during SSR
2216 * and timestamp is queried
2217 */
2218 ALOGE(" ERROR: sound card not active, return error");
2219 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 } else {
2221 return 0;
2222 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223 } else
2224 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225}
2226
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002227static int out_add_audio_effect(const struct audio_stream *stream __unused,
2228 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229{
2230 return 0;
2231}
2232
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002233static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2234 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235{
2236 return 0;
2237}
2238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002239static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2240 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241{
2242 return -EINVAL;
2243}
2244
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002245static int out_get_presentation_position(const struct audio_stream_out *stream,
2246 uint64_t *frames, struct timespec *timestamp)
2247{
2248 struct stream_out *out = (struct stream_out *)stream;
2249 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002250 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002251
2252 pthread_mutex_lock(&out->lock);
2253
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002254 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002255 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302256 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002257 &out->sample_rate);
2258 ALOGVV("%s rendered frames %ld sample_rate %d",
2259 __func__, dsp_frames, out->sample_rate);
2260 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302261 if (ret < 0)
2262 ret = -errno;
2263 if (-ENETRESET == ret) {
2264 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2265 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2266 ret = -EINVAL;
2267 } else
2268 ret = 0;
2269
Eric Laurent949a0892013-09-20 09:20:13 -07002270 /* this is the best we can do */
2271 clock_gettime(CLOCK_MONOTONIC, timestamp);
2272 }
2273 } else {
2274 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002275 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002276 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2277 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002278 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002279 // This adjustment accounts for buffering after app processor.
2280 // It is based on estimated DSP latency per use case, rather than exact.
2281 signed_frames -=
2282 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2283
Eric Laurent949a0892013-09-20 09:20:13 -07002284 // It would be unusual for this value to be negative, but check just in case ...
2285 if (signed_frames >= 0) {
2286 *frames = signed_frames;
2287 ret = 0;
2288 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002289 }
2290 }
2291 }
2292
2293 pthread_mutex_unlock(&out->lock);
2294
2295 return ret;
2296}
2297
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298static int out_set_callback(struct audio_stream_out *stream,
2299 stream_callback_t callback, void *cookie)
2300{
2301 struct stream_out *out = (struct stream_out *)stream;
2302
2303 ALOGV("%s", __func__);
2304 pthread_mutex_lock(&out->lock);
2305 out->offload_callback = callback;
2306 out->offload_cookie = cookie;
2307 pthread_mutex_unlock(&out->lock);
2308 return 0;
2309}
2310
2311static int out_pause(struct audio_stream_out* stream)
2312{
2313 struct stream_out *out = (struct stream_out *)stream;
2314 int status = -ENOSYS;
2315 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002316 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002317 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002318 pthread_mutex_lock(&out->lock);
2319 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302320 struct audio_device *adev = out->dev;
2321 int snd_scard_state = get_snd_card_state(adev);
2322
2323 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2324 status = compress_pause(out->compr);
2325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002326 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002327
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302328 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002329 audio_extn_dts_notify_playback_state(out->usecase, 0,
2330 out->sample_rate, popcount(out->channel_mask),
2331 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 }
2333 pthread_mutex_unlock(&out->lock);
2334 }
2335 return status;
2336}
2337
2338static int out_resume(struct audio_stream_out* stream)
2339{
2340 struct stream_out *out = (struct stream_out *)stream;
2341 int status = -ENOSYS;
2342 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002343 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002344 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 status = 0;
2346 pthread_mutex_lock(&out->lock);
2347 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302348 struct audio_device *adev = out->dev;
2349 int snd_scard_state = get_snd_card_state(adev);
2350
2351 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2352 status = compress_resume(out->compr);
2353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002355
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302356 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002357 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2358 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 }
2360 pthread_mutex_unlock(&out->lock);
2361 }
2362 return status;
2363}
2364
2365static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2366{
2367 struct stream_out *out = (struct stream_out *)stream;
2368 int status = -ENOSYS;
2369 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002370 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 pthread_mutex_lock(&out->lock);
2372 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2373 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2374 else
2375 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2376 pthread_mutex_unlock(&out->lock);
2377 }
2378 return status;
2379}
2380
2381static int out_flush(struct audio_stream_out* stream)
2382{
2383 struct stream_out *out = (struct stream_out *)stream;
2384 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002385 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002386 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 pthread_mutex_lock(&out->lock);
2388 stop_compressed_output_l(out);
2389 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002390 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 return 0;
2392 }
2393 return -ENOSYS;
2394}
2395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396/** audio_stream_in implementation **/
2397static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2398{
2399 struct stream_in *in = (struct stream_in *)stream;
2400
2401 return in->config.rate;
2402}
2403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002404static int in_set_sample_rate(struct audio_stream *stream __unused,
2405 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406{
2407 return -ENOSYS;
2408}
2409
2410static size_t in_get_buffer_size(const struct audio_stream *stream)
2411{
2412 struct stream_in *in = (struct stream_in *)stream;
2413
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002414 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2415 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002416 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2417 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002418
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002419 return in->config.period_size *
2420 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421}
2422
2423static uint32_t in_get_channels(const struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426
2427 return in->channel_mask;
2428}
2429
2430static audio_format_t in_get_format(const struct audio_stream *stream)
2431{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002432 struct stream_in *in = (struct stream_in *)stream;
2433
2434 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435}
2436
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002437static int in_set_format(struct audio_stream *stream __unused,
2438 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439{
2440 return -ENOSYS;
2441}
2442
2443static int in_standby(struct audio_stream *stream)
2444{
2445 struct stream_in *in = (struct stream_in *)stream;
2446 struct audio_device *adev = in->dev;
2447 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302448 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2449 stream, in->usecase, use_case_table[in->usecase]);
2450
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002451 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2452 /* Ignore standby in case of voip call because the voip input
2453 * stream is closed in adev_close_input_stream()
2454 */
2455 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2456 return status;
2457 }
2458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002460 if (!in->standby && in->is_st_session) {
2461 ALOGD("%s: sound trigger pcm stop lab", __func__);
2462 audio_extn_sound_trigger_stop_lab(in);
2463 in->standby = 1;
2464 }
2465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002467 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002469 if (in->pcm) {
2470 pcm_close(in->pcm);
2471 in->pcm = NULL;
2472 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002474 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 }
2476 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002477 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 return status;
2479}
2480
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002481static int in_dump(const struct audio_stream *stream __unused,
2482 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483{
2484 return 0;
2485}
2486
2487static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2488{
2489 struct stream_in *in = (struct stream_in *)stream;
2490 struct audio_device *adev = in->dev;
2491 struct str_parms *parms;
2492 char *str;
2493 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002494 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302496 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 parms = str_parms_create_str(kvpairs);
2498
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302499 if (!parms)
2500 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002502 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002503
2504 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2505 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 val = atoi(value);
2507 /* no audio source uses val == 0 */
2508 if ((in->source != val) && (val != 0)) {
2509 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002510 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2511 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2512 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2513 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002514 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002515 err = voice_extn_compress_voip_open_input_stream(in);
2516 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002517 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002518 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002519 }
2520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 }
2522 }
2523
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002524 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2525 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002527 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 in->device = val;
2529 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002530 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002531 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 }
2533 }
2534
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002535done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538
2539 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302540error:
Eric Laurent994a6932013-07-17 11:51:42 -07002541 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 return ret;
2543}
2544
2545static char* in_get_parameters(const struct audio_stream *stream,
2546 const char *keys)
2547{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002548 struct stream_in *in = (struct stream_in *)stream;
2549 struct str_parms *query = str_parms_create_str(keys);
2550 char *str;
2551 char value[256];
2552 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002553
2554 if (!query || !reply) {
2555 ALOGE("in_get_parameters: failed to create query or reply");
2556 return NULL;
2557 }
2558
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002559 ALOGV("%s: enter: keys - %s", __func__, keys);
2560
2561 voice_extn_in_get_parameters(in, query, reply);
2562
2563 str = str_parms_to_str(reply);
2564 str_parms_destroy(query);
2565 str_parms_destroy(reply);
2566
2567 ALOGV("%s: exit: returns - %s", __func__, str);
2568 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569}
2570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002571static int in_set_gain(struct audio_stream_in *stream __unused,
2572 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573{
2574 return 0;
2575}
2576
2577static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2578 size_t bytes)
2579{
2580 struct stream_in *in = (struct stream_in *)stream;
2581 struct audio_device *adev = in->dev;
2582 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302583 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586
2587 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302588 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302589 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302590 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302591 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002592 } else {
2593 if (in->is_st_session && !in->is_st_session_active) {
2594 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2595 ret= -EIO;;
2596 goto exit;
2597 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302598 }
2599 }
2600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002602 if (!in->is_st_session) {
2603 pthread_mutex_lock(&adev->lock);
2604 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2605 ret = voice_extn_compress_voip_start_input_stream(in);
2606 else
2607 ret = start_input_stream(in);
2608 pthread_mutex_unlock(&adev->lock);
2609 if (ret != 0) {
2610 goto exit;
2611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 }
2613 in->standby = 0;
2614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615
2616 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002617 if (audio_extn_ssr_get_enabled() &&
2618 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002619 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002620 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2621 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002622 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2623 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002624 else
2625 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302626 if (ret < 0)
2627 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 }
2629
2630 /*
2631 * Instead of writing zeroes here, we could trust the hardware
2632 * to always provide zeroes when muted.
2633 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302634 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2635 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 memset(buffer, 0, bytes);
2637
2638exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302639 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302640 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302641 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002642 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2643 session reading on LAB data. In this case do not set sound card state
2644 offline, instead mark this sound trigger session inactive to avoid
2645 further reading of LAB data from CPE driver. Marking the session
2646 inactive handles both CPE and ADSP SSR for sound trigger session */
2647 if (!in->is_st_session)
2648 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2649 else
2650 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302651 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 pthread_mutex_unlock(&in->lock);
2653
2654 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302655 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302656 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302657 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302658 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302659 in->standby = true;
2660 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302661 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002663 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002664 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302665 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 }
2667 return bytes;
2668}
2669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002670static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671{
2672 return 0;
2673}
2674
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002675static int add_remove_audio_effect(const struct audio_stream *stream,
2676 effect_handle_t effect,
2677 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002679 struct stream_in *in = (struct stream_in *)stream;
2680 int status = 0;
2681 effect_descriptor_t desc;
2682
2683 status = (*effect)->get_descriptor(effect, &desc);
2684 if (status != 0)
2685 return status;
2686
2687 pthread_mutex_lock(&in->lock);
2688 pthread_mutex_lock(&in->dev->lock);
2689 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2690 in->enable_aec != enable &&
2691 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2692 in->enable_aec = enable;
2693 if (!in->standby)
2694 select_devices(in->dev, in->usecase);
2695 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002696 if (in->enable_ns != enable &&
2697 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2698 in->enable_ns = enable;
2699 if (!in->standby)
2700 select_devices(in->dev, in->usecase);
2701 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002702 pthread_mutex_unlock(&in->dev->lock);
2703 pthread_mutex_unlock(&in->lock);
2704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 return 0;
2706}
2707
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002708static int in_add_audio_effect(const struct audio_stream *stream,
2709 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710{
Eric Laurent994a6932013-07-17 11:51:42 -07002711 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712 return add_remove_audio_effect(stream, effect, true);
2713}
2714
2715static int in_remove_audio_effect(const struct audio_stream *stream,
2716 effect_handle_t effect)
2717{
Eric Laurent994a6932013-07-17 11:51:42 -07002718 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002719 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720}
2721
2722static int adev_open_output_stream(struct audio_hw_device *dev,
2723 audio_io_handle_t handle,
2724 audio_devices_t devices,
2725 audio_output_flags_t flags,
2726 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002727 struct audio_stream_out **stream_out,
2728 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
2730 struct audio_device *adev = (struct audio_device *)dev;
2731 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002732 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002733 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302736
2737 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2738 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2739 ALOGE(" sound card is not active rejecting compress output open request");
2740 return -EINVAL;
2741 }
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2744
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302745 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2746 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2747 devices, flags, &out->stream);
2748
2749
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002750 if (!out) {
2751 return -ENOMEM;
2752 }
2753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 if (devices == AUDIO_DEVICE_NONE)
2755 devices = AUDIO_DEVICE_OUT_SPEAKER;
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 out->flags = flags;
2758 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002759 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002760 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 out->sample_rate = config->sample_rate;
2762 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2763 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002764 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002765 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002766 out->non_blocking = 0;
2767 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768
2769 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002770 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2771 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2772 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2773
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002774 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002775 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2776 ret = read_hdmi_channel_masks(out);
2777
2778 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2779 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002780 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002781 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002782 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002783
2784 if (config->sample_rate == 0)
2785 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2786 if (config->channel_mask == 0)
2787 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2788
2789 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002790 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2792 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002794 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002796 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2797 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002798 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002799 ret = voice_extn_compress_voip_open_output_stream(out);
2800 if (ret != 0) {
2801 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2802 __func__, ret);
2803 goto error_open;
2804 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2806 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2807 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2808 ALOGE("%s: Unsupported Offload information", __func__);
2809 ret = -EINVAL;
2810 goto error_open;
2811 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002812
2813 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2814 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2815 ALOGV("read and update_pass through formats");
2816 ret = audio_extn_dolby_update_passt_formats(adev, out);
2817 if(ret != 0) {
2818 goto error_open;
2819 }
2820 if(config->offload_info.format == 0)
2821 config->offload_info.format = out->supported_formats[0];
2822 }
2823
Mingming Yin90310102013-11-13 16:57:00 -08002824 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002825 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826 ALOGE("%s: Unsupported audio format", __func__);
2827 ret = -EINVAL;
2828 goto error_open;
2829 }
2830
2831 out->compr_config.codec = (struct snd_codec *)
2832 calloc(1, sizeof(struct snd_codec));
2833
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002834 if (!out->compr_config.codec) {
2835 ret = -ENOMEM;
2836 goto error_open;
2837 }
2838
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002839 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840 if (config->offload_info.channel_mask)
2841 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002842 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002844 config->offload_info.channel_mask = config->channel_mask;
2845 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002846 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 out->sample_rate = config->offload_info.sample_rate;
2848
2849 out->stream.set_callback = out_set_callback;
2850 out->stream.pause = out_pause;
2851 out->stream.resume = out_resume;
2852 out->stream.drain = out_drain;
2853 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002854 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002856 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002857 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002858 audio_extn_dolby_get_snd_codec_id(adev, out,
2859 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002860 else
2861 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002863 if (audio_is_offload_pcm(config->offload_info.format)) {
2864 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002865 platform_get_pcm_offload_buffer_size(&config->offload_info);
2866 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2867 out->compr_config.fragment_size =
2868 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002869 } else {
2870 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002871 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002872 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2874 out->compr_config.codec->sample_rate =
2875 compress_get_alsa_rate(config->offload_info.sample_rate);
2876 out->compr_config.codec->bit_rate =
2877 config->offload_info.bit_rate;
2878 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002879 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002881 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002882 /*TODO: Do we need to change it for passthrough */
2883 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884
Mingming Yin3ee55c62014-08-04 14:23:35 -07002885 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2886 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002887 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2888 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002889 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002890 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2891
Mingming Yin3ee55c62014-08-04 14:23:35 -07002892 if (out->bit_width == 24) {
2893 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2894 }
2895
Amit Shekhar6f461b12014-08-01 14:52:58 -07002896 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002897 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002898
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2900 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002901
Alexy Josephaa54c872014-12-03 02:46:47 -08002902 if (config->offload_info.use_small_bufs) {
2903 //this flag is set from framework only if its for PCM formats
2904 //no need to check for PCM format again
2905 out->non_blocking = 0;
2906 out->use_small_bufs = true;
2907 ALOGI("Keep write blocking for small buff: non_blockling %d",
2908 out->non_blocking);
2909 }
2910
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002911 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002912 out->offload_state = OFFLOAD_STATE_IDLE;
2913 out->playback_started = 0;
2914
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002915 audio_extn_dts_create_state_notifier_node(out->usecase);
2916
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002917 create_offload_callback_thread(out);
2918 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2919 __func__, config->offload_info.version,
2920 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002921 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002922 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002923 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2924 ret = voice_check_and_set_incall_music_usecase(adev, out);
2925 if (ret != 0) {
2926 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2927 __func__, ret);
2928 goto error_open;
2929 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002930 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2931 if (config->sample_rate == 0)
2932 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2933 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2934 config->sample_rate != 8000) {
2935 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2936 ret = -EINVAL;
2937 goto error_open;
2938 }
2939 out->sample_rate = config->sample_rate;
2940 out->config.rate = config->sample_rate;
2941 if (config->format == AUDIO_FORMAT_DEFAULT)
2942 config->format = AUDIO_FORMAT_PCM_16_BIT;
2943 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2944 config->format = AUDIO_FORMAT_PCM_16_BIT;
2945 ret = -EINVAL;
2946 goto error_open;
2947 }
2948 out->format = config->format;
2949 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2950 out->config = pcm_config_afe_proxy_playback;
2951 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002952 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002953 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2955 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002957 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2958 format = AUDIO_FORMAT_PCM_16_BIT;
2959 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2960 out->config = pcm_config_deep_buffer;
2961 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002962 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002963 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002964 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002965 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002966 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002967 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 }
2969
Amit Shekhar1d896042014-10-03 13:16:09 -07002970 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2971 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002972 /* TODO remove this hardcoding and check why width is zero*/
2973 if (out->bit_width == 0)
2974 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002975 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2976 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002977 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002978 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002979 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2980 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2981 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002982 if(adev->primary_output == NULL)
2983 adev->primary_output = out;
2984 else {
2985 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002986 ret = -EEXIST;
2987 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002988 }
2989 }
2990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 /* Check if this usecase is already existing */
2992 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002993 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2994 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002997 ret = -EEXIST;
2998 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 }
3000 pthread_mutex_unlock(&adev->lock);
3001
3002 out->stream.common.get_sample_rate = out_get_sample_rate;
3003 out->stream.common.set_sample_rate = out_set_sample_rate;
3004 out->stream.common.get_buffer_size = out_get_buffer_size;
3005 out->stream.common.get_channels = out_get_channels;
3006 out->stream.common.get_format = out_get_format;
3007 out->stream.common.set_format = out_set_format;
3008 out->stream.common.standby = out_standby;
3009 out->stream.common.dump = out_dump;
3010 out->stream.common.set_parameters = out_set_parameters;
3011 out->stream.common.get_parameters = out_get_parameters;
3012 out->stream.common.add_audio_effect = out_add_audio_effect;
3013 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3014 out->stream.get_latency = out_get_latency;
3015 out->stream.set_volume = out_set_volume;
3016 out->stream.write = out_write;
3017 out->stream.get_render_position = out_get_render_position;
3018 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003019 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003022 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003023 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003025 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3026 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 config->format = out->stream.common.get_format(&out->stream.common);
3029 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3030 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3031
3032 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303033 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3034 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003035
3036 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3037 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3038 popcount(out->channel_mask), out->playback_started);
3039
Eric Laurent994a6932013-07-17 11:51:42 -07003040 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003042
3043error_open:
3044 free(out);
3045 *stream_out = NULL;
3046 ALOGD("%s: exit: ret %d", __func__, ret);
3047 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048}
3049
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003050static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 struct audio_stream_out *stream)
3052{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 struct stream_out *out = (struct stream_out *)stream;
3054 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003055 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303057 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3058
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003059 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303060 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303062 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003063 if(ret != 0)
3064 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3065 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003066 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003067 out_standby(&stream->common);
3068
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003069 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003070 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003072 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 if (out->compr_config.codec != NULL)
3074 free(out->compr_config.codec);
3075 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003076
3077 if (adev->voice_tx_output == out)
3078 adev->voice_tx_output = NULL;
3079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 pthread_cond_destroy(&out->cond);
3081 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003083 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084}
3085
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003086static void close_compress_sessions(struct audio_device *adev)
3087{
Mingming Yin7b762e72015-03-04 13:47:32 -08003088 struct stream_out *out;
3089 struct listnode *node;
3090 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003091 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003092 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003093 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003094 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003095 if (usecase && usecase->stream.out) {
3096 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3097 out = usecase->stream.out;
3098 pthread_mutex_unlock(&adev->lock);
3099 out_standby(&out->stream.common);
3100 pthread_mutex_lock(&adev->lock);
3101 }
3102 }
3103 }
3104 pthread_mutex_unlock(&adev->lock);
3105}
3106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3108{
3109 struct audio_device *adev = (struct audio_device *)dev;
3110 struct str_parms *parms;
3111 char *str;
3112 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003113 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003114 int ret;
3115 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003117 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303120 if (!parms)
3121 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003122 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3123 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303124 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303125 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303126 struct listnode *node;
3127 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303128 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303129 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003130 //close compress sessions on OFFLINE status
3131 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132 } else if (strstr(snd_card_status, "ONLINE")) {
3133 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303134 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303135 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303136 }
3137
3138 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003139 status = voice_set_parameters(adev, parms);
3140 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003141 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003143 status = platform_set_parameters(adev->platform, parms);
3144 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003145 goto done;
3146
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003147 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3148 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003149 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3151 adev->bluetooth_nrec = true;
3152 else
3153 adev->bluetooth_nrec = false;
3154 }
3155
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003156 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3157 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3159 adev->screen_off = false;
3160 else
3161 adev->screen_off = true;
3162 }
3163
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003164 ret = str_parms_get_int(parms, "rotation", &val);
3165 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003166 bool reverse_speakers = false;
3167 switch(val) {
3168 // FIXME: note that the code below assumes that the speakers are in the correct placement
3169 // relative to the user when the device is rotated 90deg from its default rotation. This
3170 // assumption is device-specific, not platform-specific like this code.
3171 case 270:
3172 reverse_speakers = true;
3173 break;
3174 case 0:
3175 case 90:
3176 case 180:
3177 break;
3178 default:
3179 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003181 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003182 if (status == 0) {
3183 if (adev->speaker_lr_swap != reverse_speakers) {
3184 adev->speaker_lr_swap = reverse_speakers;
3185 // only update the selected device if there is active pcm playback
3186 struct audio_usecase *usecase;
3187 struct listnode *node;
3188 list_for_each(node, &adev->usecase_list) {
3189 usecase = node_to_item(node, struct audio_usecase, list);
3190 if (usecase->type == PCM_PLAYBACK) {
3191 select_devices(adev, usecase->id);
3192 break;
3193 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003194 }
3195 }
3196 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 }
3198
Mingming Yin514a8bc2014-07-29 15:22:21 -07003199 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3200 if (ret >= 0) {
3201 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3202 adev->bt_wb_speech_enabled = true;
3203 else
3204 adev->bt_wb_speech_enabled = false;
3205 }
3206
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003207 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3208 if (ret >= 0) {
3209 val = atoi(value);
3210 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3211 ALOGV("cache new edid");
3212 platform_cache_edid(adev->platform);
3213 }
3214 }
3215
3216 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3217 if (ret >= 0) {
3218 val = atoi(value);
3219 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3220 ALOGV("invalidate cached edid");
3221 platform_invalidate_edid(adev->platform);
3222 }
3223 }
3224
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003225 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003226
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003227done:
3228 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003229 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303230error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003231 ALOGV("%s: exit with code(%d)", __func__, status);
3232 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233}
3234
3235static char* adev_get_parameters(const struct audio_hw_device *dev,
3236 const char *keys)
3237{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003238 struct audio_device *adev = (struct audio_device *)dev;
3239 struct str_parms *reply = str_parms_create();
3240 struct str_parms *query = str_parms_create_str(keys);
3241 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303242 char value[256] = {0};
3243 int ret = 0;
3244
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003245 if (!query || !reply) {
3246 ALOGE("adev_get_parameters: failed to create query or reply");
3247 return NULL;
3248 }
3249
Naresh Tannirud7205b62014-06-20 02:54:48 +05303250 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3251 sizeof(value));
3252 if (ret >=0) {
3253 int val = 1;
3254 pthread_mutex_lock(&adev->snd_card_status.lock);
3255 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3256 val = 0;
3257 pthread_mutex_unlock(&adev->snd_card_status.lock);
3258 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3259 goto exit;
3260 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003261
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003262 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003263 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003264 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003265 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303266 pthread_mutex_unlock(&adev->lock);
3267
Naresh Tannirud7205b62014-06-20 02:54:48 +05303268exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003269 str = str_parms_to_str(reply);
3270 str_parms_destroy(query);
3271 str_parms_destroy(reply);
3272
3273 ALOGV("%s: exit: returns - %s", __func__, str);
3274 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003277static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278{
3279 return 0;
3280}
3281
3282static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3283{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003284 int ret;
3285 struct audio_device *adev = (struct audio_device *)dev;
3286 pthread_mutex_lock(&adev->lock);
3287 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003288 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003289 pthread_mutex_unlock(&adev->lock);
3290 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291}
3292
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003293static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3294 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295{
3296 return -ENOSYS;
3297}
3298
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003299static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3300 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301{
3302 return -ENOSYS;
3303}
3304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003305static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3306 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
3308 return -ENOSYS;
3309}
3310
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003311static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3312 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return -ENOSYS;
3315}
3316
3317static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3318{
3319 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 pthread_mutex_lock(&adev->lock);
3322 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003323 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003325 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3326 voice_is_in_call(adev)) {
3327 voice_stop_call(adev);
3328 adev->current_call_output = NULL;
3329 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 }
3331 pthread_mutex_unlock(&adev->lock);
3332 return 0;
3333}
3334
3335static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3336{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003337 int ret;
3338
3339 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003340 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003341 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3342 pthread_mutex_unlock(&adev->lock);
3343
3344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
3347static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3348{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003349 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 return 0;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 const struct audio_config *config)
3355{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003356 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003358 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3359 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360}
3361
3362static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003363 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 audio_devices_t devices,
3365 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003366 struct audio_stream_in **stream_in,
3367 audio_input_flags_t flags __unused,
3368 const char *address __unused,
3369 audio_source_t source __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370{
3371 struct audio_device *adev = (struct audio_device *)dev;
3372 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003373 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003374 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003375 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 *stream_in = NULL;
3378 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3379 return -EINVAL;
3380
3381 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003382
3383 if (!in) {
3384 ALOGE("failed to allocate input stream");
3385 return -ENOMEM;
3386 }
3387
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303388 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003389 stream_handle(%p) io_handle(%d)",__func__, config->sample_rate, config->channel_mask,
3390 devices, &in->stream, handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003392 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 in->stream.common.get_sample_rate = in_get_sample_rate;
3395 in->stream.common.set_sample_rate = in_set_sample_rate;
3396 in->stream.common.get_buffer_size = in_get_buffer_size;
3397 in->stream.common.get_channels = in_get_channels;
3398 in->stream.common.get_format = in_get_format;
3399 in->stream.common.set_format = in_set_format;
3400 in->stream.common.standby = in_standby;
3401 in->stream.common.dump = in_dump;
3402 in->stream.common.set_parameters = in_set_parameters;
3403 in->stream.common.get_parameters = in_get_parameters;
3404 in->stream.common.add_audio_effect = in_add_audio_effect;
3405 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3406 in->stream.set_gain = in_set_gain;
3407 in->stream.read = in_read;
3408 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3409
3410 in->device = devices;
3411 in->source = AUDIO_SOURCE_DEFAULT;
3412 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 in->standby = 1;
3414 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003415 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
3417 /* Update config params with the requested sample rate and channels */
3418 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003419 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3420 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3421 is_low_latency = true;
3422#if LOW_LATENCY_CAPTURE_USE_CASE
3423 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3424#endif
3425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003428 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003430 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303431 if (adev->mode != AUDIO_MODE_IN_CALL) {
3432 ret = -EINVAL;
3433 goto err_open;
3434 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003435 if (config->sample_rate == 0)
3436 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3437 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3438 config->sample_rate != 8000) {
3439 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3440 ret = -EINVAL;
3441 goto err_open;
3442 }
3443 if (config->format == AUDIO_FORMAT_DEFAULT)
3444 config->format = AUDIO_FORMAT_PCM_16_BIT;
3445 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3446 config->format = AUDIO_FORMAT_PCM_16_BIT;
3447 ret = -EINVAL;
3448 goto err_open;
3449 }
3450
3451 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3452 in->config = pcm_config_afe_proxy_record;
3453 in->config.channels = channel_count;
3454 in->config.rate = config->sample_rate;
3455 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003456 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003457 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003458 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3459 ret = -EINVAL;
3460 goto err_open;
3461 }
3462 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003463 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003464 }
Mingming Yine62d7842013-10-25 16:26:03 -07003465 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003466 audio_extn_compr_cap_format_supported(config->format) &&
3467 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003468 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003469 } else {
3470 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003471 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003472 buffer_size = get_input_buffer_size(config->sample_rate,
3473 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003474 channel_count,
3475 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003476 in->config.period_size = buffer_size / frame_size;
3477 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003478
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003479 /* This stream could be for sound trigger lab,
3480 get sound trigger pcm if present */
3481 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303482 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003485 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003486 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487
3488err_open:
3489 free(in);
3490 *stream_in = NULL;
3491 return ret;
3492}
3493
3494static void adev_close_input_stream(struct audio_hw_device *dev,
3495 struct audio_stream_in *stream)
3496{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003497 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003498 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003499 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303500
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303501 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003502
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303503 /* Disable echo reference while closing input stream */
3504 platform_set_echo_reference(adev->platform, false);
3505
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003506 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303507 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003508 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303509 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003510 if (ret != 0)
3511 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3512 __func__, ret);
3513 } else
3514 in_standby(&stream->common);
3515
Mingming Yin7b762e72015-03-04 13:47:32 -08003516 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003517 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003518 audio_extn_ssr_deinit();
3519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
Mingming Yine62d7842013-10-25 16:26:03 -07003521 if(audio_extn_compr_cap_enabled() &&
3522 audio_extn_compr_cap_format_supported(in->config.format))
3523 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003524
3525 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 return;
3527}
3528
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003529static int adev_dump(const audio_hw_device_t *device __unused,
3530 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531{
3532 return 0;
3533}
3534
3535static int adev_close(hw_device_t *device)
3536{
3537 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003538
3539 if (!adev)
3540 return 0;
3541
3542 pthread_mutex_lock(&adev_init_lock);
3543
3544 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003545 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003546 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003547 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003548 audio_route_free(adev->audio_route);
3549 free(adev->snd_dev_ref_cnt);
3550 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003551 free(device);
3552 adev = NULL;
3553 }
3554 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 return 0;
3556}
3557
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003558/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3559 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3560 * just that it _might_ work.
3561 */
3562static int period_size_is_plausible_for_low_latency(int period_size)
3563{
3564 switch (period_size) {
3565 case 160:
3566 case 240:
3567 case 320:
3568 case 480:
3569 return 1;
3570 default:
3571 return 0;
3572 }
3573}
3574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575static int adev_open(const hw_module_t *module, const char *name,
3576 hw_device_t **device)
3577{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003578 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003580 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3582
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003583 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003584 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003585 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003586 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003587 ALOGD("%s: returning existing instance of adev", __func__);
3588 ALOGD("%s: exit", __func__);
3589 pthread_mutex_unlock(&adev_init_lock);
3590 return 0;
3591 }
3592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 adev = calloc(1, sizeof(struct audio_device));
3594
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003595 if (!adev) {
3596 pthread_mutex_unlock(&adev_init_lock);
3597 return -ENOMEM;
3598 }
3599
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003600 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3603 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3604 adev->device.common.module = (struct hw_module_t *)module;
3605 adev->device.common.close = adev_close;
3606
3607 adev->device.init_check = adev_init_check;
3608 adev->device.set_voice_volume = adev_set_voice_volume;
3609 adev->device.set_master_volume = adev_set_master_volume;
3610 adev->device.get_master_volume = adev_get_master_volume;
3611 adev->device.set_master_mute = adev_set_master_mute;
3612 adev->device.get_master_mute = adev_get_master_mute;
3613 adev->device.set_mode = adev_set_mode;
3614 adev->device.set_mic_mute = adev_set_mic_mute;
3615 adev->device.get_mic_mute = adev_get_mic_mute;
3616 adev->device.set_parameters = adev_set_parameters;
3617 adev->device.get_parameters = adev_get_parameters;
3618 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3619 adev->device.open_output_stream = adev_open_output_stream;
3620 adev->device.close_output_stream = adev_close_output_stream;
3621 adev->device.open_input_stream = adev_open_input_stream;
3622 adev->device.close_input_stream = adev_close_input_stream;
3623 adev->device.dump = adev_dump;
3624
3625 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003627 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003628 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003631 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003632 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003633 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3634 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003635 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003636 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003637 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003638 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003639 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303640
3641 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3642 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003644 adev->platform = platform_init(adev);
3645 if (!adev->platform) {
3646 free(adev->snd_dev_ref_cnt);
3647 free(adev);
3648 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3649 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003650 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003651 return -EINVAL;
3652 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003653
Naresh Tanniru4c630392014-05-12 01:05:52 +05303654 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3655
Eric Laurentc4aef752013-09-12 17:45:53 -07003656 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3657 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3658 if (adev->visualizer_lib == NULL) {
3659 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3660 } else {
3661 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3662 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003663 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003664 "visualizer_hal_start_output");
3665 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003666 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003667 "visualizer_hal_stop_output");
3668 }
3669 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003670 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003671 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003672
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003673 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3674 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3675 if (adev->offload_effects_lib == NULL) {
3676 ALOGE("%s: DLOPEN failed for %s", __func__,
3677 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3678 } else {
3679 ALOGV("%s: DLOPEN successful for %s", __func__,
3680 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3681 adev->offload_effects_start_output =
3682 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3683 "offload_effects_bundle_hal_start_output");
3684 adev->offload_effects_stop_output =
3685 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3686 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003687 adev->offload_effects_set_hpx_state =
3688 (int (*)(bool))dlsym(adev->offload_effects_lib,
3689 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003690 }
3691 }
3692
Mingming Yin514a8bc2014-07-29 15:22:21 -07003693 adev->bt_wb_speech_enabled = false;
3694
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003695 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 *device = &adev->device.common;
3697
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003698 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3699 &adev->streams_output_cfg_list);
3700
Kiran Kandi910e1862013-10-29 13:29:42 -07003701 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003702
3703 char value[PROPERTY_VALUE_MAX];
3704 int trial;
3705 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3706 trial = atoi(value);
3707 if (period_size_is_plausible_for_low_latency(trial)) {
3708 pcm_config_low_latency.period_size = trial;
3709 pcm_config_low_latency.start_threshold = trial / 4;
3710 pcm_config_low_latency.avail_min = trial / 4;
3711 configured_low_latency_capture_period_size = trial;
3712 }
3713 }
3714 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3715 trial = atoi(value);
3716 if (period_size_is_plausible_for_low_latency(trial)) {
3717 configured_low_latency_capture_period_size = trial;
3718 }
3719 }
3720
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003721 pthread_mutex_unlock(&adev_init_lock);
3722
Eric Laurent994a6932013-07-17 11:51:42 -07003723 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 return 0;
3725}
3726
3727static struct hw_module_methods_t hal_module_methods = {
3728 .open = adev_open,
3729};
3730
3731struct audio_module HAL_MODULE_INFO_SYM = {
3732 .common = {
3733 .tag = HARDWARE_MODULE_TAG,
3734 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3735 .hal_api_version = HARDWARE_HAL_API_VERSION,
3736 .id = AUDIO_HARDWARE_MODULE_ID,
3737 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003738 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 .methods = &hal_module_methods,
3740 },
3741};