blob: a47fe7790bbb12593b3f61980c5451eafec4cc7a [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 ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700446 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800490 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700492 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
493 adev->snd_dev_ref_cnt[snd_device]--;
494 return -EINVAL;
495 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200496 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 if (audio_extn_spkr_prot_start_processing(snd_device)) {
498 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200499 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800500 return -EINVAL;
501 }
502 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 ALOGV("%s: snd_device(%d: %s)", __func__,
504 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700505 /* due to the possibility of calibration overwrite between listen
506 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700507 audio_extn_sound_trigger_update_device_status(snd_device,
508 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530509 audio_extn_listen_update_device_status(snd_device,
510 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700511 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700513 audio_extn_sound_trigger_update_device_status(snd_device,
514 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530515 audio_extn_listen_update_device_status(snd_device,
516 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700517 return -EINVAL;
518 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300519 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 return 0;
523}
524
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700526 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
529
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800530 if (snd_device < SND_DEVICE_MIN ||
531 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800532 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800533 return -EINVAL;
534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
536 ALOGE("%s: device ref cnt is already 0", __func__);
537 return -EINVAL;
538 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700548 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800550 /* exit usb play back thread */
551 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
552 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
553 audio_extn_usb_stop_playback();
554
555 /* exit usb capture thread */
556 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700557 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530559 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700562 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300563 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700564 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200567 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568 audio_extn_sound_trigger_update_device_status(snd_device,
569 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530570 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800571 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 return 0;
575}
576
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577static void check_usecases_codec_backend(struct audio_device *adev,
578 struct audio_usecase *uc_info,
579 snd_device_t snd_device)
580{
581 struct listnode *node;
582 struct audio_usecase *usecase;
583 bool switch_device[AUDIO_USECASE_MAX];
584 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530585 int backend_idx = DEFAULT_CODEC_BACKEND;
586 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587
588 /*
589 * This function is to make sure that all the usecases that are active on
590 * the hardware codec backend are always routed to any one device that is
591 * handled by the hardware codec.
592 * For example, if low-latency and deep-buffer usecases are currently active
593 * on speaker and out_set_parameters(headset) is received on low-latency
594 * output, then we have to make sure deep-buffer is also switched to headset,
595 * because of the limitation that both the devices cannot be enabled
596 * at the same time as they share the same backend.
597 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700598 /*
599 * This call is to check if we need to force routing for a particular stream
600 * If there is a backend configuration change for the device when a
601 * new stream starts, then ADM needs to be closed and re-opened with the new
602 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530603 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700604 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530605 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
606 snd_device);
607 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800609 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800610 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 for (i = 0; i < AUDIO_USECASE_MAX; i++)
612 switch_device[i] = false;
613
614 list_for_each(node, &adev->usecase_list) {
615 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530616
617 if (usecase == uc_info)
618 continue;
619 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
620 ALOGV("%s: backend_idx: %d,"
621 "usecase_backend_idx: %d, curr device: %s, usecase device:"
622 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530623 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530624
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800625 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700626 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530627 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
628 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530629 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530630 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700631 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700632 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 switch_device[usecase->id] = true;
634 num_uc_to_switch++;
635 }
636 }
637
638 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700639 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530641 /* Make sure the previous devices to be disabled first and then enable the
642 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 list_for_each(node, &adev->usecase_list) {
644 usecase = node_to_item(node, struct audio_usecase, list);
645 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700646 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 }
648 }
649
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700650 list_for_each(node, &adev->usecase_list) {
651 usecase = node_to_item(node, struct audio_usecase, list);
652 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700653 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700654 }
655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 /* Re-route all the usecases on the shared backend other than the
658 specified usecase to new snd devices */
659 list_for_each(node, &adev->usecase_list) {
660 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530661 /* Update the out_snd_device only for the usecases that are enabled here */
662 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
663 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530664 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 }
666 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 }
668}
669
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670static void check_and_route_capture_usecases(struct audio_device *adev,
671 struct audio_usecase *uc_info,
672 snd_device_t snd_device)
673{
674 struct listnode *node;
675 struct audio_usecase *usecase;
676 bool switch_device[AUDIO_USECASE_MAX];
677 int i, num_uc_to_switch = 0;
678
679 /*
680 * This function is to make sure that all the active capture usecases
681 * are always routed to the same input sound device.
682 * For example, if audio-record and voice-call usecases are currently
683 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
684 * is received for voice call then we have to make sure that audio-record
685 * usecase is also switched to earpiece i.e. voice-dmic-ef,
686 * because of the limitation that two devices cannot be enabled
687 * at the same time if they share the same backend.
688 */
689 for (i = 0; i < AUDIO_USECASE_MAX; i++)
690 switch_device[i] = false;
691
692 list_for_each(node, &adev->usecase_list) {
693 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800694 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700696 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700697 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
698 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700699 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700700 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
701 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700702 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700703 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 switch_device[usecase->id] = true;
705 num_uc_to_switch++;
706 }
707 }
708
709 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700710 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700711
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530712 /* Make sure the previous devices to be disabled first and then enable the
713 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714 list_for_each(node, &adev->usecase_list) {
715 usecase = node_to_item(node, struct audio_usecase, list);
716 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700717 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800718 }
719 }
720
721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
723 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700724 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700725 }
726 }
727
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728 /* Re-route all the usecases on the shared backend other than the
729 specified usecase to new snd devices */
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 /* Update the in_snd_device only before enabling the audio route */
733 if (switch_device[usecase->id] ) {
734 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800735 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530736 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700737 }
738 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700739 }
740}
741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800742/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700743static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700745 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700746 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747
748 switch (channels) {
749 /*
750 * Do not handle stereo output in Multi-channel cases
751 * Stereo case is handled in normal playback path
752 */
753 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700754 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
757 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
759 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 break;
761 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700762 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769 break;
770 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700771 ALOGE("HDMI does not support multi channel playback");
772 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773 break;
774 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700775 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776}
777
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800778audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
779 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700780{
781 struct audio_usecase *usecase;
782 struct listnode *node;
783
784 list_for_each(node, &adev->usecase_list) {
785 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800786 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700787 ALOGV("%s: usecase id %d", __func__, usecase->id);
788 return usecase->id;
789 }
790 }
791 return USECASE_INVALID;
792}
793
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700794struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700796{
797 struct audio_usecase *usecase;
798 struct listnode *node;
799
800 list_for_each(node, &adev->usecase_list) {
801 usecase = node_to_item(node, struct audio_usecase, list);
802 if (usecase->id == uc_id)
803 return usecase;
804 }
805 return NULL;
806}
807
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700808int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800810 snd_device_t out_snd_device = SND_DEVICE_NONE;
811 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700812 struct audio_usecase *usecase = NULL;
813 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800814 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800815 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800816 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800817 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700818 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700820 usecase = get_usecase_from_list(adev, uc_id);
821 if (usecase == NULL) {
822 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
823 return -EINVAL;
824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800825
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800826 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800827 (usecase->type == VOIP_CALL) ||
828 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700829 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800830 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700831 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 usecase->devices = usecase->stream.out->devices;
833 } else {
834 /*
835 * If the voice call is active, use the sound devices of voice call usecase
836 * so that it would not result any device switch. All the usecases will
837 * be switched to new device when select_devices() is called for voice call
838 * usecase. This is to avoid switching devices for voice call when
839 * check_usecases_codec_backend() is called below.
840 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700841 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800843 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700844 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
845 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 in_snd_device = vc_usecase->in_snd_device;
847 out_snd_device = vc_usecase->out_snd_device;
848 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800849 } else if (voice_extn_compress_voip_is_active(adev)) {
850 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700851 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530852 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700853 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800854 in_snd_device = voip_usecase->in_snd_device;
855 out_snd_device = voip_usecase->out_snd_device;
856 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800857 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800858 hfp_ucid = audio_extn_hfp_get_usecase();
859 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700860 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800861 in_snd_device = hfp_usecase->in_snd_device;
862 out_snd_device = hfp_usecase->out_snd_device;
863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 }
865 if (usecase->type == PCM_PLAYBACK) {
866 usecase->devices = usecase->stream.out->devices;
867 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700868 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700869 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800870 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700871 if (usecase->stream.out == adev->primary_output &&
872 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800873 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700874 select_devices(adev, adev->active_input->usecase);
875 }
876 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 } else if (usecase->type == PCM_CAPTURE) {
878 usecase->devices = usecase->stream.in->device;
879 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700881 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530882 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
883 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
884 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
885 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700886 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800887 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700888 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
889 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700890 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 }
895
896 if (out_snd_device == usecase->out_snd_device &&
897 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800898 return 0;
899 }
900
sangwoobc677242013-08-08 16:53:43 +0900901 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700902 out_snd_device, platform_get_snd_device_name(out_snd_device),
903 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 /*
906 * Limitation: While in call, to do a device switch we need to disable
907 * and enable both RX and TX devices though one of them is same as current
908 * device.
909 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700910 if ((usecase->type == VOICE_CALL) &&
911 (usecase->in_snd_device != SND_DEVICE_NONE) &&
912 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700913 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700914 /* Disable sidetone only if voice call already exists */
915 if (voice_is_call_state_active(adev))
916 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800917 }
918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 /* Disable current sound devices */
920 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700921 disable_audio_route(adev, usecase);
922 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923 }
924
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700926 disable_audio_route(adev, usecase);
927 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 }
929
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800930 /* Applicable only on the targets that has external modem.
931 * New device information should be sent to modem before enabling
932 * the devices to reduce in-call device switch time.
933 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700934 if ((usecase->type == VOICE_CALL) &&
935 (usecase->in_snd_device != SND_DEVICE_NONE) &&
936 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800937 status = platform_switch_voice_call_enable_device_config(adev->platform,
938 out_snd_device,
939 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700940 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 /* Enable new sound devices */
943 if (out_snd_device != SND_DEVICE_NONE) {
944 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
945 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700946 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947 }
948
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 if (in_snd_device != SND_DEVICE_NONE) {
950 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700951 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953
Avinash Vaish71a8b972014-07-24 15:36:33 +0530954 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700955 status = platform_switch_voice_call_device_post(adev->platform,
956 out_snd_device,
957 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530958 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700959 /* Enable sidetone only if voice call already exists */
960 if (voice_is_call_state_active(adev))
961 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530962 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800963
sangwoo170731f2013-06-08 15:36:36 +0900964 usecase->in_snd_device = in_snd_device;
965 usecase->out_snd_device = out_snd_device;
966
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530967 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700968 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530969 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700970 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530971 usecase->stream.out->flags,
972 usecase->stream.out->format,
973 usecase->stream.out->sample_rate,
974 usecase->stream.out->bit_width,
975 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700976 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530977 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700978
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700979 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900980
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800981 /* Applicable only on the targets that has external modem.
982 * Enable device command should be sent to modem only after
983 * enabling voice call mixer controls
984 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700985 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800986 status = platform_switch_voice_call_usecase_route_post(adev->platform,
987 out_snd_device,
988 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530989 ALOGD("%s: done",__func__);
990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 return status;
992}
993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994static int stop_input_stream(struct stream_in *in)
995{
996 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 struct audio_usecase *uc_info;
998 struct audio_device *adev = in->dev;
999
Eric Laurentc8400632013-02-14 19:04:54 -08001000 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001
Eric Laurent994a6932013-07-17 11:51:42 -07001002 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004 uc_info = get_usecase_from_list(adev, in->usecase);
1005 if (uc_info == NULL) {
1006 ALOGE("%s: Could not find the usecase (%d) in the list",
1007 __func__, in->usecase);
1008 return -EINVAL;
1009 }
1010
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001011 /* Close in-call recording streams */
1012 voice_check_and_stop_incall_rec_usecase(adev, in);
1013
Eric Laurent150dbfe2013-02-27 14:31:02 -08001014 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001015 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016
1017 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001018 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001020 list_remove(&uc_info->list);
1021 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Eric Laurent994a6932013-07-17 11:51:42 -07001023 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 return ret;
1025}
1026
1027int start_input_stream(struct stream_in *in)
1028{
1029 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001030 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 struct audio_usecase *uc_info;
1032 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301033 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034
Mingming Yine62d7842013-10-25 16:26:03 -07001035 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301036 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1037 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001038
Naresh Tanniru80659832014-06-04 18:17:56 +05301039
1040 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301041 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301042 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301043 goto error_config;
1044 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301045
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001046 /* Check if source matches incall recording usecase criteria */
1047 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1048 if (ret)
1049 goto error_config;
1050 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001051 ALOGD("%s: Updated usecase(%d: %s)",
1052 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001053
Eric Laurentb23d5282013-05-14 15:27:20 -07001054 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055 if (in->pcm_device_id < 0) {
1056 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1057 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001058 ret = -EINVAL;
1059 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061
1062 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001064
1065 if (!uc_info) {
1066 ret = -ENOMEM;
1067 goto error_config;
1068 }
1069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 uc_info->id = in->usecase;
1071 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001072 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 uc_info->devices = in->device;
1074 uc_info->in_snd_device = SND_DEVICE_NONE;
1075 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001077 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301078 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001079 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080
Eric Laurentc8400632013-02-14 19:04:54 -08001081 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001082 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1083
1084 unsigned int flags = PCM_IN;
1085 unsigned int pcm_open_retry_count = 0;
1086
1087 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1088 flags |= PCM_MMAP | PCM_NOIRQ;
1089 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1090 }
1091
1092 while (1) {
1093 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1094 flags, &in->config);
1095 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1096 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1097 if (in->pcm != NULL) {
1098 pcm_close(in->pcm);
1099 in->pcm = NULL;
1100 }
1101 if (pcm_open_retry_count-- == 0) {
1102 ret = -EIO;
1103 goto error_open;
1104 }
1105 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1106 continue;
1107 }
1108 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001109 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301110 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301111
Eric Laurent994a6932013-07-17 11:51:42 -07001112 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001113 return ret;
1114
1115error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301117 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001118
1119error_config:
1120 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001122
1123 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124}
1125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001126/* must be called with out->lock locked */
1127static int send_offload_cmd_l(struct stream_out* out, int command)
1128{
1129 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1130
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001131 if (!cmd) {
1132 ALOGE("failed to allocate mem for command 0x%x", command);
1133 return -ENOMEM;
1134 }
1135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001136 ALOGVV("%s %d", __func__, command);
1137
1138 cmd->cmd = command;
1139 list_add_tail(&out->offload_cmd_list, &cmd->node);
1140 pthread_cond_signal(&out->offload_cond);
1141 return 0;
1142}
1143
1144/* must be called iwth out->lock locked */
1145static void stop_compressed_output_l(struct stream_out *out)
1146{
1147 out->offload_state = OFFLOAD_STATE_IDLE;
1148 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001149 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001150 if (out->compr != NULL) {
1151 compress_stop(out->compr);
1152 while (out->offload_thread_blocked) {
1153 pthread_cond_wait(&out->cond, &out->lock);
1154 }
1155 }
1156}
1157
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001158bool is_offload_usecase(audio_usecase_t uc_id)
1159{
1160 unsigned int i;
1161 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1162 if (uc_id == offload_usecases[i])
1163 return true;
1164 }
1165 return false;
1166}
1167
1168static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1169{
1170 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1171 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1172 char value[PROPERTY_VALUE_MAX] = {0};
1173
1174 property_get("audio.offload.multiple.enabled", value, NULL);
1175 if (!(atoi(value) || !strncmp("true", value, 4)))
1176 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1177
1178 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1179 for (i = 0; i < num_usecase; i++) {
1180 if (!(adev->offload_usecases_state & (0x1<<i))) {
1181 adev->offload_usecases_state |= 0x1 << i;
1182 ret = offload_usecases[i];
1183 break;
1184 }
1185 }
1186 ALOGV("%s: offload usecase is %d", __func__, ret);
1187 return ret;
1188}
1189
1190static void free_offload_usecase(struct audio_device *adev,
1191 audio_usecase_t uc_id)
1192{
1193 unsigned int i;
1194 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1195 if (offload_usecases[i] == uc_id) {
1196 adev->offload_usecases_state &= ~(0x1<<i);
1197 break;
1198 }
1199 }
1200 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1201}
1202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203static void *offload_thread_loop(void *context)
1204{
1205 struct stream_out *out = (struct stream_out *) context;
1206 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001207 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001208
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001209 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1210 set_sched_policy(0, SP_FOREGROUND);
1211 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1212
1213 ALOGV("%s", __func__);
1214 pthread_mutex_lock(&out->lock);
1215 for (;;) {
1216 struct offload_cmd *cmd = NULL;
1217 stream_callback_event_t event;
1218 bool send_callback = false;
1219
1220 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1221 __func__, list_empty(&out->offload_cmd_list),
1222 out->offload_state);
1223 if (list_empty(&out->offload_cmd_list)) {
1224 ALOGV("%s SLEEPING", __func__);
1225 pthread_cond_wait(&out->offload_cond, &out->lock);
1226 ALOGV("%s RUNNING", __func__);
1227 continue;
1228 }
1229
1230 item = list_head(&out->offload_cmd_list);
1231 cmd = node_to_item(item, struct offload_cmd, node);
1232 list_remove(item);
1233
1234 ALOGVV("%s STATE %d CMD %d out->compr %p",
1235 __func__, out->offload_state, cmd->cmd, out->compr);
1236
1237 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1238 free(cmd);
1239 break;
1240 }
1241
1242 if (out->compr == NULL) {
1243 ALOGE("%s: Compress handle is NULL", __func__);
1244 pthread_cond_signal(&out->cond);
1245 continue;
1246 }
1247 out->offload_thread_blocked = true;
1248 pthread_mutex_unlock(&out->lock);
1249 send_callback = false;
1250 switch(cmd->cmd) {
1251 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001252 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001253 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001254 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001255 send_callback = true;
1256 event = STREAM_CBK_EVENT_WRITE_READY;
1257 break;
1258 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001259 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301260 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001261 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301262 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001263 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301264 if (ret < 0)
1265 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301266 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301267 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001268 compress_drain(out->compr);
1269 else
1270 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301271 if (ret != -ENETRESET) {
1272 send_callback = true;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301273 pthread_mutex_lock(&out->lock);
1274 out->send_new_metadata = 1;
1275 out->send_next_track_params = true;
1276 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301277 event = STREAM_CBK_EVENT_DRAIN_READY;
1278 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1279 } else
1280 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001281 break;
1282 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001283 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001284 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001285 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001286 send_callback = true;
1287 event = STREAM_CBK_EVENT_DRAIN_READY;
1288 break;
1289 default:
1290 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1291 break;
1292 }
1293 pthread_mutex_lock(&out->lock);
1294 out->offload_thread_blocked = false;
1295 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001296 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001297 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001298 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001299 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001300 free(cmd);
1301 }
1302
1303 pthread_cond_signal(&out->cond);
1304 while (!list_empty(&out->offload_cmd_list)) {
1305 item = list_head(&out->offload_cmd_list);
1306 list_remove(item);
1307 free(node_to_item(item, struct offload_cmd, node));
1308 }
1309 pthread_mutex_unlock(&out->lock);
1310
1311 return NULL;
1312}
1313
1314static int create_offload_callback_thread(struct stream_out *out)
1315{
1316 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1317 list_init(&out->offload_cmd_list);
1318 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1319 offload_thread_loop, out);
1320 return 0;
1321}
1322
1323static int destroy_offload_callback_thread(struct stream_out *out)
1324{
1325 pthread_mutex_lock(&out->lock);
1326 stop_compressed_output_l(out);
1327 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1328
1329 pthread_mutex_unlock(&out->lock);
1330 pthread_join(out->offload_thread, (void **) NULL);
1331 pthread_cond_destroy(&out->offload_cond);
1332
1333 return 0;
1334}
1335
Eric Laurent07eeafd2013-10-06 12:52:49 -07001336static bool allow_hdmi_channel_config(struct audio_device *adev)
1337{
1338 struct listnode *node;
1339 struct audio_usecase *usecase;
1340 bool ret = true;
1341
1342 list_for_each(node, &adev->usecase_list) {
1343 usecase = node_to_item(node, struct audio_usecase, list);
1344 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1345 /*
1346 * If voice call is already existing, do not proceed further to avoid
1347 * disabling/enabling both RX and TX devices, CSD calls, etc.
1348 * Once the voice call done, the HDMI channels can be configured to
1349 * max channels of remaining use cases.
1350 */
1351 if (usecase->id == USECASE_VOICE_CALL) {
1352 ALOGD("%s: voice call is active, no change in HDMI channels",
1353 __func__);
1354 ret = false;
1355 break;
1356 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1357 ALOGD("%s: multi channel playback is active, "
1358 "no change in HDMI channels", __func__);
1359 ret = false;
1360 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001361 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001362 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001363 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1364 ", no change in HDMI channels", __func__,
1365 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001366 ret = false;
1367 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001368 }
1369 }
1370 }
1371 return ret;
1372}
1373
1374static int check_and_set_hdmi_channels(struct audio_device *adev,
1375 unsigned int channels)
1376{
1377 struct listnode *node;
1378 struct audio_usecase *usecase;
1379
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001380 unsigned int supported_channels = platform_edid_get_max_channels(
1381 adev->platform);
1382 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001383 /* Check if change in HDMI channel config is allowed */
1384 if (!allow_hdmi_channel_config(adev))
1385 return 0;
1386
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001387 if (channels > supported_channels)
1388 channels = supported_channels;
1389
Eric Laurent07eeafd2013-10-06 12:52:49 -07001390 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001391 ALOGD("%s: Requested channels are same as current channels(%d)",
1392 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001393 return 0;
1394 }
1395
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001396 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001397 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001398 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001399 adev->cur_hdmi_channels = channels;
1400
1401 /*
1402 * Deroute all the playback streams routed to HDMI so that
1403 * the back end is deactivated. Note that backend will not
1404 * be deactivated if any one stream is connected to it.
1405 */
1406 list_for_each(node, &adev->usecase_list) {
1407 usecase = node_to_item(node, struct audio_usecase, list);
1408 if (usecase->type == PCM_PLAYBACK &&
1409 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001410 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001411 }
1412 }
1413
1414 /*
1415 * Enable all the streams disabled above. Now the HDMI backend
1416 * will be activated with new channel configuration
1417 */
1418 list_for_each(node, &adev->usecase_list) {
1419 usecase = node_to_item(node, struct audio_usecase, list);
1420 if (usecase->type == PCM_PLAYBACK &&
1421 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 }
1424 }
1425
1426 return 0;
1427}
1428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429static int stop_output_stream(struct stream_out *out)
1430{
1431 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 struct audio_usecase *uc_info;
1433 struct audio_device *adev = out->dev;
1434
Eric Laurent994a6932013-07-17 11:51:42 -07001435 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001436 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 uc_info = get_usecase_from_list(adev, out->usecase);
1438 if (uc_info == NULL) {
1439 ALOGE("%s: Could not find the usecase (%d) in the list",
1440 __func__, out->usecase);
1441 return -EINVAL;
1442 }
1443
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001444 if (is_offload_usecase(out->usecase) &&
1445 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001446 if (adev->visualizer_stop_output != NULL)
1447 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001448
1449 audio_extn_dts_remove_state_notifier_node(out->usecase);
1450
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001451 if (adev->offload_effects_stop_output != NULL)
1452 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1453 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001454
Eric Laurent150dbfe2013-02-27 14:31:02 -08001455 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001456 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457
1458 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001459 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001461 list_remove(&uc_info->list);
1462 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001464 if (is_offload_usecase(out->usecase) &&
1465 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1466 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1467 ALOGV("Disable passthrough , reset mixer to pcm");
1468 /* NO_PASSTHROUGH */
1469 out->compr_config.codec->compr_passthr = 0;
1470 audio_extn_dolby_set_hdmi_config(adev, out);
1471 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1472 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001473 /* Must be called after removing the usecase from list */
1474 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1475 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1476
Eric Laurent994a6932013-07-17 11:51:42 -07001477 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 return ret;
1479}
1480
1481int start_output_stream(struct stream_out *out)
1482{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001484 int sink_channels = 0;
1485 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 struct audio_usecase *uc_info;
1487 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301488 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001490 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1491 ret = -EINVAL;
1492 goto error_config;
1493 }
1494
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301495 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1496 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1497 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301498
Naresh Tanniru80659832014-06-04 18:17:56 +05301499 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301500 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301501 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301502 goto error_config;
1503 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301504
Eric Laurentb23d5282013-05-14 15:27:20 -07001505 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 if (out->pcm_device_id < 0) {
1507 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1508 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001509 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001510 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 }
1512
1513 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001514
1515 if (!uc_info) {
1516 ret = -ENOMEM;
1517 goto error_config;
1518 }
1519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520 uc_info->id = out->usecase;
1521 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001522 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523 uc_info->devices = out->devices;
1524 uc_info->in_snd_device = SND_DEVICE_NONE;
1525 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001526 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001527 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001528 if (is_offload_usecase(out->usecase)) {
1529 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001530 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1531 }
1532 }
Mingming Yin9c041392014-05-01 15:37:31 -07001533 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1534 if (!strncmp("true", prop_value, 4)) {
1535 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001536 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1537 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001538 check_and_set_hdmi_channels(adev, sink_channels);
1539 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001540 if (is_offload_usecase(out->usecase)) {
1541 unsigned int ch_count = out->compr_config.codec->ch_in;
1542 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1543 /* backend channel config for passthrough stream is stereo */
1544 ch_count = 2;
1545 check_and_set_hdmi_channels(adev, ch_count);
1546 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001547 check_and_set_hdmi_channels(adev, out->config.channels);
1548 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001549 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001550 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001551 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 select_devices(adev, out->usecase);
1554
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001555 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1556 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001557 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001558 unsigned int flags = PCM_OUT;
1559 unsigned int pcm_open_retry_count = 0;
1560 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1561 flags |= PCM_MMAP | PCM_NOIRQ;
1562 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1563 } else
1564 flags |= PCM_MONOTONIC;
1565
1566 while (1) {
1567 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1568 flags, &out->config);
1569 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1570 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1571 if (out->pcm != NULL) {
1572 pcm_close(out->pcm);
1573 out->pcm = NULL;
1574 }
1575 if (pcm_open_retry_count-- == 0) {
1576 ret = -EIO;
1577 goto error_open;
1578 }
1579 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1580 continue;
1581 }
1582 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001584 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1585 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001587 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1588 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001590 out->compr = compress_open(adev->snd_card,
1591 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001592 COMPRESS_IN, &out->compr_config);
1593 if (out->compr && !is_compress_ready(out->compr)) {
1594 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1595 compress_close(out->compr);
1596 out->compr = NULL;
1597 ret = -EIO;
1598 goto error_open;
1599 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301600 /* compress_open sends params of the track, so reset the flag here */
1601 out->is_compr_metadata_avail = false;
1602
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 if (out->offload_callback)
1604 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001605
Fred Oh3f43e742015-03-04 18:42:34 -08001606 /* Since small bufs uses blocking writes, a write will be blocked
1607 for the default max poll time (20s) in the event of an SSR.
1608 Reduce the poll time to observe and deal with SSR faster.
1609 */
1610 if (out->use_small_bufs) {
1611 compress_set_max_poll_wait(out->compr, 1000);
1612 }
1613
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001614 audio_extn_dts_create_state_notifier_node(out->usecase);
1615 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1616 popcount(out->channel_mask),
1617 out->playback_started);
1618
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001619#ifdef DS1_DOLBY_DDP_ENABLED
1620 if (audio_extn_is_dolby_format(out->format))
1621 audio_extn_dolby_send_ddp_endp_params(adev);
1622#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001623 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1624 if (adev->visualizer_start_output != NULL)
1625 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1626 if (adev->offload_effects_start_output != NULL)
1627 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001628 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630 }
Eric Laurent994a6932013-07-17 11:51:42 -07001631 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001633error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001635error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637}
1638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639static int check_input_parameters(uint32_t sample_rate,
1640 audio_format_t format,
1641 int channel_count)
1642{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001643 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001645 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001646 !voice_extn_compress_voip_is_format_supported(format) &&
1647 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001648
1649 switch (channel_count) {
1650 case 1:
1651 case 2:
1652 case 6:
1653 break;
1654 default:
1655 ret = -EINVAL;
1656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
1658 switch (sample_rate) {
1659 case 8000:
1660 case 11025:
1661 case 12000:
1662 case 16000:
1663 case 22050:
1664 case 24000:
1665 case 32000:
1666 case 44100:
1667 case 48000:
1668 break;
1669 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001670 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 }
1672
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001673 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674}
1675
1676static size_t get_input_buffer_size(uint32_t sample_rate,
1677 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001678 int channel_count,
1679 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680{
1681 size_t size = 0;
1682
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001683 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1684 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001686 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001687 if (is_low_latency)
1688 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001689 /* ToDo: should use frame_size computed based on the format and
1690 channel_count here. */
1691 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001693 /* make sure the size is multiple of 32 bytes
1694 * At 48 kHz mono 16-bit PCM:
1695 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1696 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1697 */
1698 size += 0x1f;
1699 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001700
1701 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702}
1703
1704static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1705{
1706 struct stream_out *out = (struct stream_out *)stream;
1707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709}
1710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001711static int out_set_sample_rate(struct audio_stream *stream __unused,
1712 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713{
1714 return -ENOSYS;
1715}
1716
1717static size_t out_get_buffer_size(const struct audio_stream *stream)
1718{
1719 struct stream_out *out = (struct stream_out *)stream;
1720
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001721 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001723 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1724 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001726 return out->config.period_size *
1727 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728}
1729
1730static uint32_t out_get_channels(const struct audio_stream *stream)
1731{
1732 struct stream_out *out = (struct stream_out *)stream;
1733
1734 return out->channel_mask;
1735}
1736
1737static audio_format_t out_get_format(const struct audio_stream *stream)
1738{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 struct stream_out *out = (struct stream_out *)stream;
1740
1741 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742}
1743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001744static int out_set_format(struct audio_stream *stream __unused,
1745 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746{
1747 return -ENOSYS;
1748}
1749
1750static int out_standby(struct audio_stream *stream)
1751{
1752 struct stream_out *out = (struct stream_out *)stream;
1753 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301755 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1756 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001757 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1758 /* Ignore standby in case of voip call because the voip output
1759 * stream is closed in adev_close_output_stream()
1760 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301761 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 return 0;
1763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001767 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001769 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 if (out->pcm) {
1771 pcm_close(out->pcm);
1772 out->pcm = NULL;
1773 }
1774 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001775 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001776 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301777 out->send_next_track_params = false;
1778 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001779 out->gapless_mdata.encoder_delay = 0;
1780 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 if (out->compr != NULL) {
1782 compress_close(out->compr);
1783 out->compr = NULL;
1784 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001785 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001787 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 }
1789 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001790 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 return 0;
1792}
1793
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001794static int out_dump(const struct audio_stream *stream __unused,
1795 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796{
1797 return 0;
1798}
1799
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001800static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1801{
1802 int ret = 0;
1803 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001804
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001806 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001807 return -EINVAL;
1808 }
1809
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001810 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1811 if (ret >= 0) {
1812 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1813 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1814 ALOGV("ADTS format is set in offload mode");
1815 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001816 }
1817
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301818 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001819
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001820 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1821 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301822 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001824 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1825 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301826 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 }
1828
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829 ALOGV("%s new encoder delay %u and padding %u", __func__,
1830 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1831
1832 return 0;
1833}
1834
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001835static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1836{
1837 return out == adev->primary_output || out == adev->voice_tx_output;
1838}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1841{
1842 struct stream_out *out = (struct stream_out *)stream;
1843 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001844 struct audio_usecase *usecase;
1845 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 struct str_parms *parms;
1847 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001848 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001849 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850
sangwoobc677242013-08-08 16:53:43 +09001851 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001852 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301854 if (!parms)
1855 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001856 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1857 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001860 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001862 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301863 * When HDMI cable is unplugged/usb hs is disconnected the
1864 * music playback is paused and the policy manager sends routing=0
1865 * But the audioflingercontinues to write data until standby time
1866 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 * Avoid this by routing audio to speaker until standby.
1868 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301869 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1870 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001871 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001872 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1873 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 }
1875
1876 /*
1877 * select_devices() call below switches all the usecases on the same
1878 * backend to the new device. Refer to check_usecases_codec_backend() in
1879 * the select_devices(). But how do we undo this?
1880 *
1881 * For example, music playback is active on headset (deep-buffer usecase)
1882 * and if we go to ringtones and select a ringtone, low-latency usecase
1883 * will be started on headset+speaker. As we can't enable headset+speaker
1884 * and headset devices at the same time, select_devices() switches the music
1885 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1886 * So when the ringtone playback is completed, how do we undo the same?
1887 *
1888 * We are relying on the out_set_parameters() call on deep-buffer output,
1889 * once the ringtone playback is ended.
1890 * NOTE: We should not check if the current devices are same as new devices.
1891 * Because select_devices() must be called to switch back the music
1892 * playback to headset.
1893 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001894 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 out->devices = val;
1896
1897 if (!out->standby)
1898 select_devices(adev, out->usecase);
1899
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001900 if (output_drives_call(adev, out)) {
1901 if(!voice_is_in_call(adev)) {
1902 if (adev->mode == AUDIO_MODE_IN_CALL) {
1903 adev->current_call_output = out;
1904 ret = voice_start_call(adev);
1905 }
1906 } else {
1907 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001908 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001909 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001910 }
1911 }
1912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001914 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001916
1917 if (out == adev->primary_output) {
1918 pthread_mutex_lock(&adev->lock);
1919 audio_extn_set_parameters(adev, parms);
1920 pthread_mutex_unlock(&adev->lock);
1921 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001922 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001923 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001924 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001925
1926 audio_extn_dts_create_state_notifier_node(out->usecase);
1927 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1928 popcount(out->channel_mask),
1929 out->playback_started);
1930
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001931 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001932 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301935error:
Eric Laurent994a6932013-07-17 11:51:42 -07001936 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 return ret;
1938}
1939
1940static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1941{
1942 struct stream_out *out = (struct stream_out *)stream;
1943 struct str_parms *query = str_parms_create_str(keys);
1944 char *str;
1945 char value[256];
1946 struct str_parms *reply = str_parms_create();
1947 size_t i, j;
1948 int ret;
1949 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001950
1951 if (!query || !reply) {
1952 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1953 return NULL;
1954 }
1955
Eric Laurent994a6932013-07-17 11:51:42 -07001956 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1958 if (ret >= 0) {
1959 value[0] = '\0';
1960 i = 0;
1961 while (out->supported_channel_masks[i] != 0) {
1962 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1963 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1964 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001965 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001967 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 first = false;
1969 break;
1970 }
1971 }
1972 i++;
1973 }
1974 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1975 str = str_parms_to_str(reply);
1976 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001977 voice_extn_out_get_parameters(out, query, reply);
1978 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001979 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001980 free(str);
1981 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001982 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001984
1985 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1986 if (ret >= 0) {
1987 value[0] = '\0';
1988 i = 0;
1989 first = true;
1990 while (out->supported_formats[i] != 0) {
1991 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1992 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1993 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001994 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001995 }
1996 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1997 first = false;
1998 break;
1999 }
2000 }
2001 i++;
2002 }
2003 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2004 str = str_parms_to_str(reply);
2005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006 str_parms_destroy(query);
2007 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002008 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 return str;
2010}
2011
2012static uint32_t out_get_latency(const struct audio_stream_out *stream)
2013{
2014 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002015 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
Alexy Josephaa54c872014-12-03 02:46:47 -08002017 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002018 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002019 } else {
2020 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002022 }
2023
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302024 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002025 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026}
2027
2028static int out_set_volume(struct audio_stream_out *stream, float left,
2029 float right)
2030{
Eric Laurenta9024de2013-04-04 09:19:12 -07002031 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 int volume[2];
2033
Eric Laurenta9024de2013-04-04 09:19:12 -07002034 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2035 /* only take left channel into account: the API is for stereo anyway */
2036 out->muted = (left == 0.0f);
2037 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002038 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002039 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2040 /*
2041 * Set mute or umute on HDMI passthrough stream.
2042 * Only take left channel into account.
2043 * Mute is 0 and unmute 1
2044 */
2045 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2046 } else {
2047 char mixer_ctl_name[128];
2048 struct audio_device *adev = out->dev;
2049 struct mixer_ctl *ctl;
2050 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002051 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002053 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2054 "Compress Playback %d Volume", pcm_device_id);
2055 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2056 if (!ctl) {
2057 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2058 __func__, mixer_ctl_name);
2059 return -EINVAL;
2060 }
2061 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2062 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2063 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2064 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002066 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 return -ENOSYS;
2069}
2070
2071static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2072 size_t bytes)
2073{
2074 struct stream_out *out = (struct stream_out *)stream;
2075 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302076 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002077 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302080
Naresh Tanniru80659832014-06-04 18:17:56 +05302081 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002082 // increase written size during SSR to avoid mismatch
2083 // with the written frames count in AF
2084 if (!is_offload_usecase(out->usecase))
2085 out->written += bytes / (out->config.channels * sizeof(short));
2086
Naresh Tanniru80659832014-06-04 18:17:56 +05302087 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302088 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302089 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302090 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002091 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302092 //during SSR for compress usecase we should return error to flinger
2093 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2094 pthread_mutex_unlock(&out->lock);
2095 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302096 }
2097 }
2098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002100 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002101 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002102 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2103 ret = voice_extn_compress_voip_start_output_stream(out);
2104 else
2105 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002106 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002107 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002109 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 goto exit;
2111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002114 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002115 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002116 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002117 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002118 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2119 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302120 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2121 ALOGD("copl(%p):send next track params in gapless", out);
2122 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2123 out->send_next_track_params = false;
2124 out->is_compr_metadata_avail = false;
2125 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 }
2127
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302129 if (ret < 0)
2130 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002131 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002132 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302133 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302135 } else if (-ENETRESET == ret) {
2136 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2137 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2138 pthread_mutex_unlock(&out->lock);
2139 out_standby(&out->stream.common);
2140 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302142 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002144 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 out->playback_started = 1;
2146 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002147
2148 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2149 popcount(out->channel_mask),
2150 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 }
2152 pthread_mutex_unlock(&out->lock);
2153 return ret;
2154 } else {
2155 if (out->pcm) {
2156 if (out->muted)
2157 memset((void *)buffer, 0, bytes);
2158 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002159 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2160 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2161 else
2162 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302163 if (ret < 0)
2164 ret = -errno;
2165 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002166 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 }
2169
2170exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302171 /* ToDo: There may be a corner case when SSR happens back to back during
2172 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302173 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302174 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302175 }
2176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 pthread_mutex_unlock(&out->lock);
2178
2179 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002180 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002181 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302182 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302183 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302184 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302185 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302186 out->standby = true;
2187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002189 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302190 out_get_sample_rate(&out->stream.common));
2191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 }
2193 return bytes;
2194}
2195
2196static int out_get_render_position(const struct audio_stream_out *stream,
2197 uint32_t *dsp_frames)
2198{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302200 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002201
2202 if (dsp_frames == NULL)
2203 return -EINVAL;
2204
2205 *dsp_frames = 0;
2206 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002207 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 pthread_mutex_lock(&out->lock);
2209 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302210 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002211 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302212 if (ret < 0)
2213 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002214 ALOGVV("%s rendered frames %d sample_rate %d",
2215 __func__, *dsp_frames, out->sample_rate);
2216 }
2217 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302218 if (-ENETRESET == ret) {
2219 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2220 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2221 return -EINVAL;
2222 } else if(ret < 0) {
2223 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2224 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302225 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2226 /*
2227 * Handle corner case where compress session is closed during SSR
2228 * and timestamp is queried
2229 */
2230 ALOGE(" ERROR: sound card not active, return error");
2231 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302232 } else {
2233 return 0;
2234 }
Zhou Song32a556e2015-05-05 10:46:56 +08002235 } else if (audio_is_linear_pcm(out->format)) {
2236 *dsp_frames = out->written;
2237 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002238 } else
2239 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240}
2241
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002242static int out_add_audio_effect(const struct audio_stream *stream __unused,
2243 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244{
2245 return 0;
2246}
2247
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002248static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2249 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250{
2251 return 0;
2252}
2253
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002254static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2255 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256{
2257 return -EINVAL;
2258}
2259
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002260static int out_get_presentation_position(const struct audio_stream_out *stream,
2261 uint64_t *frames, struct timespec *timestamp)
2262{
2263 struct stream_out *out = (struct stream_out *)stream;
2264 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002265 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002266
2267 pthread_mutex_lock(&out->lock);
2268
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002269 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002270 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302271 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002272 &out->sample_rate);
2273 ALOGVV("%s rendered frames %ld sample_rate %d",
2274 __func__, dsp_frames, out->sample_rate);
2275 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302276 if (ret < 0)
2277 ret = -errno;
2278 if (-ENETRESET == ret) {
2279 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2280 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2281 ret = -EINVAL;
2282 } else
2283 ret = 0;
2284
Eric Laurent949a0892013-09-20 09:20:13 -07002285 /* this is the best we can do */
2286 clock_gettime(CLOCK_MONOTONIC, timestamp);
2287 }
2288 } else {
2289 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002290 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002291 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2292 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002293 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002294 // This adjustment accounts for buffering after app processor.
2295 // It is based on estimated DSP latency per use case, rather than exact.
2296 signed_frames -=
2297 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2298
Eric Laurent949a0892013-09-20 09:20:13 -07002299 // It would be unusual for this value to be negative, but check just in case ...
2300 if (signed_frames >= 0) {
2301 *frames = signed_frames;
2302 ret = 0;
2303 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002304 }
2305 }
2306 }
2307
2308 pthread_mutex_unlock(&out->lock);
2309
2310 return ret;
2311}
2312
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313static int out_set_callback(struct audio_stream_out *stream,
2314 stream_callback_t callback, void *cookie)
2315{
2316 struct stream_out *out = (struct stream_out *)stream;
2317
2318 ALOGV("%s", __func__);
2319 pthread_mutex_lock(&out->lock);
2320 out->offload_callback = callback;
2321 out->offload_cookie = cookie;
2322 pthread_mutex_unlock(&out->lock);
2323 return 0;
2324}
2325
2326static int out_pause(struct audio_stream_out* stream)
2327{
2328 struct stream_out *out = (struct stream_out *)stream;
2329 int status = -ENOSYS;
2330 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002331 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002332 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333 pthread_mutex_lock(&out->lock);
2334 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302335 struct audio_device *adev = out->dev;
2336 int snd_scard_state = get_snd_card_state(adev);
2337
2338 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2339 status = compress_pause(out->compr);
2340
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002342
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302343 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002344 audio_extn_dts_notify_playback_state(out->usecase, 0,
2345 out->sample_rate, popcount(out->channel_mask),
2346 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 }
2348 pthread_mutex_unlock(&out->lock);
2349 }
2350 return status;
2351}
2352
2353static int out_resume(struct audio_stream_out* stream)
2354{
2355 struct stream_out *out = (struct stream_out *)stream;
2356 int status = -ENOSYS;
2357 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002358 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002359 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002360 status = 0;
2361 pthread_mutex_lock(&out->lock);
2362 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302363 struct audio_device *adev = out->dev;
2364 int snd_scard_state = get_snd_card_state(adev);
2365
2366 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2367 status = compress_resume(out->compr);
2368
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002370
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302371 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002372 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2373 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 }
2375 pthread_mutex_unlock(&out->lock);
2376 }
2377 return status;
2378}
2379
2380static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2381{
2382 struct stream_out *out = (struct stream_out *)stream;
2383 int status = -ENOSYS;
2384 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002385 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 pthread_mutex_lock(&out->lock);
2387 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2388 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2389 else
2390 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2391 pthread_mutex_unlock(&out->lock);
2392 }
2393 return status;
2394}
2395
2396static int out_flush(struct audio_stream_out* stream)
2397{
2398 struct stream_out *out = (struct stream_out *)stream;
2399 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002400 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002401 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 pthread_mutex_lock(&out->lock);
2403 stop_compressed_output_l(out);
2404 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002405 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 return 0;
2407 }
2408 return -ENOSYS;
2409}
2410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411/** audio_stream_in implementation **/
2412static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2413{
2414 struct stream_in *in = (struct stream_in *)stream;
2415
2416 return in->config.rate;
2417}
2418
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002419static int in_set_sample_rate(struct audio_stream *stream __unused,
2420 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421{
2422 return -ENOSYS;
2423}
2424
2425static size_t in_get_buffer_size(const struct audio_stream *stream)
2426{
2427 struct stream_in *in = (struct stream_in *)stream;
2428
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002429 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2430 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002431 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2432 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002433
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002434 return in->config.period_size *
2435 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436}
2437
2438static uint32_t in_get_channels(const struct audio_stream *stream)
2439{
2440 struct stream_in *in = (struct stream_in *)stream;
2441
2442 return in->channel_mask;
2443}
2444
2445static audio_format_t in_get_format(const struct audio_stream *stream)
2446{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002447 struct stream_in *in = (struct stream_in *)stream;
2448
2449 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450}
2451
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002452static int in_set_format(struct audio_stream *stream __unused,
2453 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454{
2455 return -ENOSYS;
2456}
2457
2458static int in_standby(struct audio_stream *stream)
2459{
2460 struct stream_in *in = (struct stream_in *)stream;
2461 struct audio_device *adev = in->dev;
2462 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302463 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2464 stream, in->usecase, use_case_table[in->usecase]);
2465
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002466 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2467 /* Ignore standby in case of voip call because the voip input
2468 * stream is closed in adev_close_input_stream()
2469 */
2470 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2471 return status;
2472 }
2473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002475 if (!in->standby && in->is_st_session) {
2476 ALOGD("%s: sound trigger pcm stop lab", __func__);
2477 audio_extn_sound_trigger_stop_lab(in);
2478 in->standby = 1;
2479 }
2480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002482 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002484 if (in->pcm) {
2485 pcm_close(in->pcm);
2486 in->pcm = NULL;
2487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002489 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 }
2491 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002492 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 return status;
2494}
2495
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002496static int in_dump(const struct audio_stream *stream __unused,
2497 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498{
2499 return 0;
2500}
2501
2502static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2503{
2504 struct stream_in *in = (struct stream_in *)stream;
2505 struct audio_device *adev = in->dev;
2506 struct str_parms *parms;
2507 char *str;
2508 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002509 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302511 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 parms = str_parms_create_str(kvpairs);
2513
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302514 if (!parms)
2515 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002517 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002518
2519 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2520 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 val = atoi(value);
2522 /* no audio source uses val == 0 */
2523 if ((in->source != val) && (val != 0)) {
2524 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002525 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2526 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2527 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2528 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002529 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002530 err = voice_extn_compress_voip_open_input_stream(in);
2531 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002532 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002533 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002534 }
2535 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 }
2537 }
2538
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002539 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2540 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002542 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 in->device = val;
2544 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002545 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002546 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 }
2548 }
2549
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002550done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002552 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553
2554 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302555error:
Eric Laurent994a6932013-07-17 11:51:42 -07002556 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 return ret;
2558}
2559
2560static char* in_get_parameters(const struct audio_stream *stream,
2561 const char *keys)
2562{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002563 struct stream_in *in = (struct stream_in *)stream;
2564 struct str_parms *query = str_parms_create_str(keys);
2565 char *str;
2566 char value[256];
2567 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002568
2569 if (!query || !reply) {
2570 ALOGE("in_get_parameters: failed to create query or reply");
2571 return NULL;
2572 }
2573
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 ALOGV("%s: enter: keys - %s", __func__, keys);
2575
2576 voice_extn_in_get_parameters(in, query, reply);
2577
2578 str = str_parms_to_str(reply);
2579 str_parms_destroy(query);
2580 str_parms_destroy(reply);
2581
2582 ALOGV("%s: exit: returns - %s", __func__, str);
2583 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584}
2585
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002586static int in_set_gain(struct audio_stream_in *stream __unused,
2587 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588{
2589 return 0;
2590}
2591
2592static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2593 size_t bytes)
2594{
2595 struct stream_in *in = (struct stream_in *)stream;
2596 struct audio_device *adev = in->dev;
2597 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302598 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302601
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002602 if (in->is_st_session) {
2603 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2604 /* Read from sound trigger HAL */
2605 audio_extn_sound_trigger_read(in, buffer, bytes);
2606 pthread_mutex_unlock(&in->lock);
2607 return bytes;
2608 }
2609
2610 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2611 ALOGD(" %s: sound card is not active/SSR state", __func__);
2612 ret= -EIO;;
2613 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302614 }
2615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002617 pthread_mutex_lock(&adev->lock);
2618 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2619 ret = voice_extn_compress_voip_start_input_stream(in);
2620 else
2621 ret = start_input_stream(in);
2622 pthread_mutex_unlock(&adev->lock);
2623 if (ret != 0) {
2624 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 }
2626 in->standby = 0;
2627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
2629 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002630 if (audio_extn_ssr_get_enabled() &&
2631 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002632 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002633 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2634 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002635 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2636 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002637 else
2638 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302639 if (ret < 0)
2640 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 }
2642
2643 /*
2644 * Instead of writing zeroes here, we could trust the hardware
2645 * to always provide zeroes when muted.
2646 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302647 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2648 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 memset(buffer, 0, bytes);
2650
2651exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302652 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302653 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002654 if (-ENETRESET == ret)
2655 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 pthread_mutex_unlock(&in->lock);
2658
2659 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302660 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302661 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302662 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302663 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302664 in->standby = true;
2665 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302666 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002668 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002669 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302670 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672 return bytes;
2673}
2674
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002675static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676{
2677 return 0;
2678}
2679
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002680static int add_remove_audio_effect(const struct audio_stream *stream,
2681 effect_handle_t effect,
2682 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002684 struct stream_in *in = (struct stream_in *)stream;
2685 int status = 0;
2686 effect_descriptor_t desc;
2687
2688 status = (*effect)->get_descriptor(effect, &desc);
2689 if (status != 0)
2690 return status;
2691
2692 pthread_mutex_lock(&in->lock);
2693 pthread_mutex_lock(&in->dev->lock);
2694 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2695 in->enable_aec != enable &&
2696 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2697 in->enable_aec = enable;
2698 if (!in->standby)
2699 select_devices(in->dev, in->usecase);
2700 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002701 if (in->enable_ns != enable &&
2702 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2703 in->enable_ns = enable;
2704 if (!in->standby)
2705 select_devices(in->dev, in->usecase);
2706 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002707 pthread_mutex_unlock(&in->dev->lock);
2708 pthread_mutex_unlock(&in->lock);
2709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 return 0;
2711}
2712
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002713static int in_add_audio_effect(const struct audio_stream *stream,
2714 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715{
Eric Laurent994a6932013-07-17 11:51:42 -07002716 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002717 return add_remove_audio_effect(stream, effect, true);
2718}
2719
2720static int in_remove_audio_effect(const struct audio_stream *stream,
2721 effect_handle_t effect)
2722{
Eric Laurent994a6932013-07-17 11:51:42 -07002723 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002724 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725}
2726
2727static int adev_open_output_stream(struct audio_hw_device *dev,
2728 audio_io_handle_t handle,
2729 audio_devices_t devices,
2730 audio_output_flags_t flags,
2731 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002732 struct audio_stream_out **stream_out,
2733 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
2735 struct audio_device *adev = (struct audio_device *)dev;
2736 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002737 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002738 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302741
2742 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2743 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2744 ALOGE(" sound card is not active rejecting compress output open request");
2745 return -EINVAL;
2746 }
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2749
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302750 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2751 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2752 devices, flags, &out->stream);
2753
2754
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002755 if (!out) {
2756 return -ENOMEM;
2757 }
2758
Haynes Mathew George204045b2015-02-25 20:32:03 -08002759 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2760 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 if (devices == AUDIO_DEVICE_NONE)
2763 devices = AUDIO_DEVICE_OUT_SPEAKER;
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 out->flags = flags;
2766 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002767 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002768 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002769 out->sample_rate = config->sample_rate;
2770 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2771 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002772 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002773 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002774 out->non_blocking = 0;
2775 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776
2777 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002778 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2779 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002780 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2781 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2782
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002783 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002784 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2785 ret = read_hdmi_channel_masks(out);
2786
2787 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2788 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002789 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002790 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002791 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002792
2793 if (config->sample_rate == 0)
2794 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2795 if (config->channel_mask == 0)
2796 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2797
2798 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2801 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002803 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002805 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2806 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002807 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002808 ret = voice_extn_compress_voip_open_output_stream(out);
2809 if (ret != 0) {
2810 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2811 __func__, ret);
2812 goto error_open;
2813 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2815 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2816 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2817 ALOGE("%s: Unsupported Offload information", __func__);
2818 ret = -EINVAL;
2819 goto error_open;
2820 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002821
2822 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2823 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2824 ALOGV("read and update_pass through formats");
2825 ret = audio_extn_dolby_update_passt_formats(adev, out);
2826 if(ret != 0) {
2827 goto error_open;
2828 }
2829 if(config->offload_info.format == 0)
2830 config->offload_info.format = out->supported_formats[0];
2831 }
2832
Mingming Yin90310102013-11-13 16:57:00 -08002833 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002834 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 ALOGE("%s: Unsupported audio format", __func__);
2836 ret = -EINVAL;
2837 goto error_open;
2838 }
2839
2840 out->compr_config.codec = (struct snd_codec *)
2841 calloc(1, sizeof(struct snd_codec));
2842
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002843 if (!out->compr_config.codec) {
2844 ret = -ENOMEM;
2845 goto error_open;
2846 }
2847
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002848 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 if (config->offload_info.channel_mask)
2850 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002851 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002853 config->offload_info.channel_mask = config->channel_mask;
2854 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002855 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 out->sample_rate = config->offload_info.sample_rate;
2857
2858 out->stream.set_callback = out_set_callback;
2859 out->stream.pause = out_pause;
2860 out->stream.resume = out_resume;
2861 out->stream.drain = out_drain;
2862 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002863 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002865 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002866 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002867 audio_extn_dolby_get_snd_codec_id(adev, out,
2868 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002869 else
2870 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002872 if (audio_is_offload_pcm(config->offload_info.format)) {
2873 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002874 platform_get_pcm_offload_buffer_size(&config->offload_info);
2875 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2876 out->compr_config.fragment_size =
2877 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002878 } else {
2879 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002880 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002881 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2883 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002884 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 out->compr_config.codec->bit_rate =
2886 config->offload_info.bit_rate;
2887 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002888 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002890 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002891 /*TODO: Do we need to change it for passthrough */
2892 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893
Mingming Yin3ee55c62014-08-04 14:23:35 -07002894 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2895 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002896 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2897 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002898 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002899 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2900
Mingming Yin3ee55c62014-08-04 14:23:35 -07002901 if (out->bit_width == 24) {
2902 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2903 }
2904
Amit Shekhar6f461b12014-08-01 14:52:58 -07002905 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002906 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2909 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002910
Alexy Josephaa54c872014-12-03 02:46:47 -08002911 if (config->offload_info.use_small_bufs) {
2912 //this flag is set from framework only if its for PCM formats
2913 //no need to check for PCM format again
2914 out->non_blocking = 0;
2915 out->use_small_bufs = true;
2916 ALOGI("Keep write blocking for small buff: non_blockling %d",
2917 out->non_blocking);
2918 }
2919
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002920 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302921 out->send_next_track_params = false;
2922 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002923 out->offload_state = OFFLOAD_STATE_IDLE;
2924 out->playback_started = 0;
2925
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002926 audio_extn_dts_create_state_notifier_node(out->usecase);
2927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928 create_offload_callback_thread(out);
2929 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2930 __func__, config->offload_info.version,
2931 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002932 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002933 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002934 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2935 ret = voice_check_and_set_incall_music_usecase(adev, out);
2936 if (ret != 0) {
2937 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2938 __func__, ret);
2939 goto error_open;
2940 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002941 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2942 if (config->sample_rate == 0)
2943 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2944 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2945 config->sample_rate != 8000) {
2946 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2947 ret = -EINVAL;
2948 goto error_open;
2949 }
2950 out->sample_rate = config->sample_rate;
2951 out->config.rate = config->sample_rate;
2952 if (config->format == AUDIO_FORMAT_DEFAULT)
2953 config->format = AUDIO_FORMAT_PCM_16_BIT;
2954 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2955 config->format = AUDIO_FORMAT_PCM_16_BIT;
2956 ret = -EINVAL;
2957 goto error_open;
2958 }
2959 out->format = config->format;
2960 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2961 out->config = pcm_config_afe_proxy_playback;
2962 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002963 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002964 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2966 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002968 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2969 format = AUDIO_FORMAT_PCM_16_BIT;
2970 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2971 out->config = pcm_config_deep_buffer;
2972 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002973 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002974 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002975 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002976 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002977 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002978 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 }
2980
Amit Shekhar1d896042014-10-03 13:16:09 -07002981 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2982 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002983 /* TODO remove this hardcoding and check why width is zero*/
2984 if (out->bit_width == 0)
2985 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002986 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2987 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002988 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05302989 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002990 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2991 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2992 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002993 if(adev->primary_output == NULL)
2994 adev->primary_output = out;
2995 else {
2996 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002997 ret = -EEXIST;
2998 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002999 }
3000 }
3001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 /* Check if this usecase is already existing */
3003 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003004 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3005 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003008 ret = -EEXIST;
3009 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 }
3011 pthread_mutex_unlock(&adev->lock);
3012
3013 out->stream.common.get_sample_rate = out_get_sample_rate;
3014 out->stream.common.set_sample_rate = out_set_sample_rate;
3015 out->stream.common.get_buffer_size = out_get_buffer_size;
3016 out->stream.common.get_channels = out_get_channels;
3017 out->stream.common.get_format = out_get_format;
3018 out->stream.common.set_format = out_set_format;
3019 out->stream.common.standby = out_standby;
3020 out->stream.common.dump = out_dump;
3021 out->stream.common.set_parameters = out_set_parameters;
3022 out->stream.common.get_parameters = out_get_parameters;
3023 out->stream.common.add_audio_effect = out_add_audio_effect;
3024 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3025 out->stream.get_latency = out_get_latency;
3026 out->stream.set_volume = out_set_volume;
3027 out->stream.write = out_write;
3028 out->stream.get_render_position = out_get_render_position;
3029 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003030 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003033 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003034 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035
3036 config->format = out->stream.common.get_format(&out->stream.common);
3037 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3038 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3039
3040 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303041 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3042 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003043
3044 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3045 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3046 popcount(out->channel_mask), out->playback_started);
3047
Eric Laurent994a6932013-07-17 11:51:42 -07003048 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003050
3051error_open:
3052 free(out);
3053 *stream_out = NULL;
3054 ALOGD("%s: exit: ret %d", __func__, ret);
3055 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056}
3057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003058static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 struct audio_stream_out *stream)
3060{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 struct stream_out *out = (struct stream_out *)stream;
3062 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003063 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303065 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3066
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003067 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303068 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003069 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303070 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003071 if(ret != 0)
3072 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3073 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003074 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 out_standby(&stream->common);
3076
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003077 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003078 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003080 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081 if (out->compr_config.codec != NULL)
3082 free(out->compr_config.codec);
3083 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003084
3085 if (adev->voice_tx_output == out)
3086 adev->voice_tx_output = NULL;
3087
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 pthread_cond_destroy(&out->cond);
3089 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003091 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092}
3093
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003094static void close_compress_sessions(struct audio_device *adev)
3095{
Mingming Yin7b762e72015-03-04 13:47:32 -08003096 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303097 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003098 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003099 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303100
3101 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003102 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303103 if (is_offload_usecase(usecase->id)) {
3104 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003105 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3106 out = usecase->stream.out;
3107 pthread_mutex_unlock(&adev->lock);
3108 out_standby(&out->stream.common);
3109 pthread_mutex_lock(&adev->lock);
3110 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303111 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003112 }
3113 pthread_mutex_unlock(&adev->lock);
3114}
3115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3117{
3118 struct audio_device *adev = (struct audio_device *)dev;
3119 struct str_parms *parms;
3120 char *str;
3121 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003122 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003123 int ret;
3124 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003126 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303129 if (!parms)
3130 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003131 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3132 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303133 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303134 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303135 struct listnode *node;
3136 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303137 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303138 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003139 //close compress sessions on OFFLINE status
3140 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303141 } else if (strstr(snd_card_status, "ONLINE")) {
3142 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303143 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303144 if (!platform_is_acdb_initialized(adev->platform)) {
3145 ret = platform_acdb_init(adev->platform);
3146 if(ret)
3147 ALOGE("acdb initialization is failed");
3148
3149 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303150 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 }
3152
3153 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003154 status = voice_set_parameters(adev, parms);
3155 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003156 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003158 status = platform_set_parameters(adev->platform, parms);
3159 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003160 goto done;
3161
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003162 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3163 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003164 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3166 adev->bluetooth_nrec = true;
3167 else
3168 adev->bluetooth_nrec = false;
3169 }
3170
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3172 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3174 adev->screen_off = false;
3175 else
3176 adev->screen_off = true;
3177 }
3178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 ret = str_parms_get_int(parms, "rotation", &val);
3180 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003181 bool reverse_speakers = false;
3182 switch(val) {
3183 // FIXME: note that the code below assumes that the speakers are in the correct placement
3184 // relative to the user when the device is rotated 90deg from its default rotation. This
3185 // assumption is device-specific, not platform-specific like this code.
3186 case 270:
3187 reverse_speakers = true;
3188 break;
3189 case 0:
3190 case 90:
3191 case 180:
3192 break;
3193 default:
3194 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003195 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003196 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 if (status == 0) {
3198 if (adev->speaker_lr_swap != reverse_speakers) {
3199 adev->speaker_lr_swap = reverse_speakers;
3200 // only update the selected device if there is active pcm playback
3201 struct audio_usecase *usecase;
3202 struct listnode *node;
3203 list_for_each(node, &adev->usecase_list) {
3204 usecase = node_to_item(node, struct audio_usecase, list);
3205 if (usecase->type == PCM_PLAYBACK) {
3206 select_devices(adev, usecase->id);
3207 break;
3208 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003209 }
3210 }
3211 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003212 }
3213
Mingming Yin514a8bc2014-07-29 15:22:21 -07003214 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3215 if (ret >= 0) {
3216 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3217 adev->bt_wb_speech_enabled = true;
3218 else
3219 adev->bt_wb_speech_enabled = false;
3220 }
3221
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003222 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3223 if (ret >= 0) {
3224 val = atoi(value);
3225 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3226 ALOGV("cache new edid");
3227 platform_cache_edid(adev->platform);
3228 }
3229 }
3230
3231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3232 if (ret >= 0) {
3233 val = atoi(value);
3234 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3235 ALOGV("invalidate cached edid");
3236 platform_invalidate_edid(adev->platform);
3237 }
3238 }
3239
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003240 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003241
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003242done:
3243 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003244 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303245error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003246 ALOGV("%s: exit with code(%d)", __func__, status);
3247 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
3250static char* adev_get_parameters(const struct audio_hw_device *dev,
3251 const char *keys)
3252{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003253 struct audio_device *adev = (struct audio_device *)dev;
3254 struct str_parms *reply = str_parms_create();
3255 struct str_parms *query = str_parms_create_str(keys);
3256 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303257 char value[256] = {0};
3258 int ret = 0;
3259
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003260 if (!query || !reply) {
3261 ALOGE("adev_get_parameters: failed to create query or reply");
3262 return NULL;
3263 }
3264
Naresh Tannirud7205b62014-06-20 02:54:48 +05303265 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3266 sizeof(value));
3267 if (ret >=0) {
3268 int val = 1;
3269 pthread_mutex_lock(&adev->snd_card_status.lock);
3270 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3271 val = 0;
3272 pthread_mutex_unlock(&adev->snd_card_status.lock);
3273 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3274 goto exit;
3275 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003276
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003277 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003278 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003279 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003280 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303281 pthread_mutex_unlock(&adev->lock);
3282
Naresh Tannirud7205b62014-06-20 02:54:48 +05303283exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003284 str = str_parms_to_str(reply);
3285 str_parms_destroy(query);
3286 str_parms_destroy(reply);
3287
3288 ALOGV("%s: exit: returns - %s", __func__, str);
3289 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290}
3291
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003292static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293{
3294 return 0;
3295}
3296
3297static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3298{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003299 int ret;
3300 struct audio_device *adev = (struct audio_device *)dev;
3301 pthread_mutex_lock(&adev->lock);
3302 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003303 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003304 pthread_mutex_unlock(&adev->lock);
3305 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3309 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return -ENOSYS;
3312}
3313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003314static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3315 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return -ENOSYS;
3318}
3319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003320static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3321 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return -ENOSYS;
3324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3327 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return -ENOSYS;
3330}
3331
3332static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3333{
3334 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 pthread_mutex_lock(&adev->lock);
3337 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003338 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003340 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3341 voice_is_in_call(adev)) {
3342 voice_stop_call(adev);
3343 adev->current_call_output = NULL;
3344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 }
3346 pthread_mutex_unlock(&adev->lock);
3347 return 0;
3348}
3349
3350static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3351{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003352 int ret;
3353
3354 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003355 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003356 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3357 pthread_mutex_unlock(&adev->lock);
3358
3359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360}
3361
3362static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3363{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003364 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 return 0;
3366}
3367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003368static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 const struct audio_config *config)
3370{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003371 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003373 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3374 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375}
3376
3377static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003378 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 audio_devices_t devices,
3380 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003381 struct audio_stream_in **stream_in,
3382 audio_input_flags_t flags __unused,
3383 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003384 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385{
3386 struct audio_device *adev = (struct audio_device *)dev;
3387 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003388 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003389 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003390 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 *stream_in = NULL;
3393 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3394 return -EINVAL;
3395
3396 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003397
3398 if (!in) {
3399 ALOGE("failed to allocate input stream");
3400 return -ENOMEM;
3401 }
3402
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303403 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003404 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3405 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003407 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 in->stream.common.get_sample_rate = in_get_sample_rate;
3410 in->stream.common.set_sample_rate = in_set_sample_rate;
3411 in->stream.common.get_buffer_size = in_get_buffer_size;
3412 in->stream.common.get_channels = in_get_channels;
3413 in->stream.common.get_format = in_get_format;
3414 in->stream.common.set_format = in_set_format;
3415 in->stream.common.standby = in_standby;
3416 in->stream.common.dump = in_dump;
3417 in->stream.common.set_parameters = in_set_parameters;
3418 in->stream.common.get_parameters = in_get_parameters;
3419 in->stream.common.add_audio_effect = in_add_audio_effect;
3420 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3421 in->stream.set_gain = in_set_gain;
3422 in->stream.read = in_read;
3423 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3424
3425 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003426 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 in->standby = 1;
3429 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003430 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431
3432 /* Update config params with the requested sample rate and channels */
3433 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003434 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3435 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3436 is_low_latency = true;
3437#if LOW_LATENCY_CAPTURE_USE_CASE
3438 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3439#endif
3440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003443 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003445 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303446 if (adev->mode != AUDIO_MODE_IN_CALL) {
3447 ret = -EINVAL;
3448 goto err_open;
3449 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003450 if (config->sample_rate == 0)
3451 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3452 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3453 config->sample_rate != 8000) {
3454 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3455 ret = -EINVAL;
3456 goto err_open;
3457 }
3458 if (config->format == AUDIO_FORMAT_DEFAULT)
3459 config->format = AUDIO_FORMAT_PCM_16_BIT;
3460 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3461 config->format = AUDIO_FORMAT_PCM_16_BIT;
3462 ret = -EINVAL;
3463 goto err_open;
3464 }
3465
3466 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3467 in->config = pcm_config_afe_proxy_record;
3468 in->config.channels = channel_count;
3469 in->config.rate = config->sample_rate;
3470 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003471 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003472 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003473 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003478 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 }
Mingming Yine62d7842013-10-25 16:26:03 -07003480 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003481 audio_extn_compr_cap_format_supported(config->format) &&
3482 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003483 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003484 } else {
3485 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003486 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003487 buffer_size = get_input_buffer_size(config->sample_rate,
3488 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003489 channel_count,
3490 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003491 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003492 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3493 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3494 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3495 (in->config.rate == 8000 || in->config.rate == 16000) &&
3496 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3497 voice_extn_compress_voip_open_input_stream(in);
3498 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003501 /* This stream could be for sound trigger lab,
3502 get sound trigger pcm if present */
3503 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303504 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003507 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003508 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
3510err_open:
3511 free(in);
3512 *stream_in = NULL;
3513 return ret;
3514}
3515
3516static void adev_close_input_stream(struct audio_hw_device *dev,
3517 struct audio_stream_in *stream)
3518{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003519 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003520 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003521 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303522
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303523 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003524
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303525 /* Disable echo reference while closing input stream */
3526 platform_set_echo_reference(adev->platform, false);
3527
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003528 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303529 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003530 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303531 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003532 if (ret != 0)
3533 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3534 __func__, ret);
3535 } else
3536 in_standby(&stream->common);
3537
Mingming Yin7b762e72015-03-04 13:47:32 -08003538 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003539 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003540 audio_extn_ssr_deinit();
3541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542
Mingming Yine62d7842013-10-25 16:26:03 -07003543 if(audio_extn_compr_cap_enabled() &&
3544 audio_extn_compr_cap_format_supported(in->config.format))
3545 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003546
3547 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 return;
3549}
3550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003551static int adev_dump(const audio_hw_device_t *device __unused,
3552 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553{
3554 return 0;
3555}
3556
3557static int adev_close(hw_device_t *device)
3558{
3559 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003560
3561 if (!adev)
3562 return 0;
3563
3564 pthread_mutex_lock(&adev_init_lock);
3565
3566 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003567 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003568 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003569 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003570 audio_route_free(adev->audio_route);
3571 free(adev->snd_dev_ref_cnt);
3572 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003573 free(device);
3574 adev = NULL;
3575 }
3576 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 return 0;
3578}
3579
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003580/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3581 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3582 * just that it _might_ work.
3583 */
3584static int period_size_is_plausible_for_low_latency(int period_size)
3585{
3586 switch (period_size) {
3587 case 160:
3588 case 240:
3589 case 320:
3590 case 480:
3591 return 1;
3592 default:
3593 return 0;
3594 }
3595}
3596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597static int adev_open(const hw_module_t *module, const char *name,
3598 hw_device_t **device)
3599{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003600 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003602 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3604
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003605 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003606 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003607 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003608 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003609 ALOGD("%s: returning existing instance of adev", __func__);
3610 ALOGD("%s: exit", __func__);
3611 pthread_mutex_unlock(&adev_init_lock);
3612 return 0;
3613 }
3614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 adev = calloc(1, sizeof(struct audio_device));
3616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003617 if (!adev) {
3618 pthread_mutex_unlock(&adev_init_lock);
3619 return -ENOMEM;
3620 }
3621
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003622 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3625 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3626 adev->device.common.module = (struct hw_module_t *)module;
3627 adev->device.common.close = adev_close;
3628
3629 adev->device.init_check = adev_init_check;
3630 adev->device.set_voice_volume = adev_set_voice_volume;
3631 adev->device.set_master_volume = adev_set_master_volume;
3632 adev->device.get_master_volume = adev_get_master_volume;
3633 adev->device.set_master_mute = adev_set_master_mute;
3634 adev->device.get_master_mute = adev_get_master_mute;
3635 adev->device.set_mode = adev_set_mode;
3636 adev->device.set_mic_mute = adev_set_mic_mute;
3637 adev->device.get_mic_mute = adev_get_mic_mute;
3638 adev->device.set_parameters = adev_set_parameters;
3639 adev->device.get_parameters = adev_get_parameters;
3640 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3641 adev->device.open_output_stream = adev_open_output_stream;
3642 adev->device.close_output_stream = adev_close_output_stream;
3643 adev->device.open_input_stream = adev_open_input_stream;
3644 adev->device.close_input_stream = adev_close_input_stream;
3645 adev->device.dump = adev_dump;
3646
3647 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003649 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003650 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003653 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003654 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003655 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003656 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003657 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003658 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003659 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303660
3661 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3662 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003664 adev->platform = platform_init(adev);
3665 if (!adev->platform) {
3666 free(adev->snd_dev_ref_cnt);
3667 free(adev);
3668 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3669 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003670 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003671 return -EINVAL;
3672 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003673
Naresh Tanniru4c630392014-05-12 01:05:52 +05303674 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3675
Eric Laurentc4aef752013-09-12 17:45:53 -07003676 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3677 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3678 if (adev->visualizer_lib == NULL) {
3679 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3680 } else {
3681 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3682 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003683 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003684 "visualizer_hal_start_output");
3685 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003686 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003687 "visualizer_hal_stop_output");
3688 }
3689 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003690 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003691 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003692
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003693 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3694 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3695 if (adev->offload_effects_lib == NULL) {
3696 ALOGE("%s: DLOPEN failed for %s", __func__,
3697 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3698 } else {
3699 ALOGV("%s: DLOPEN successful for %s", __func__,
3700 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3701 adev->offload_effects_start_output =
3702 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3703 "offload_effects_bundle_hal_start_output");
3704 adev->offload_effects_stop_output =
3705 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3706 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003707 adev->offload_effects_set_hpx_state =
3708 (int (*)(bool))dlsym(adev->offload_effects_lib,
3709 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003710 }
3711 }
3712
Mingming Yin514a8bc2014-07-29 15:22:21 -07003713 adev->bt_wb_speech_enabled = false;
3714
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003715 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 *device = &adev->device.common;
3717
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003718 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3719 &adev->streams_output_cfg_list);
3720
Kiran Kandi910e1862013-10-29 13:29:42 -07003721 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003722
3723 char value[PROPERTY_VALUE_MAX];
3724 int trial;
3725 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3726 trial = atoi(value);
3727 if (period_size_is_plausible_for_low_latency(trial)) {
3728 pcm_config_low_latency.period_size = trial;
3729 pcm_config_low_latency.start_threshold = trial / 4;
3730 pcm_config_low_latency.avail_min = trial / 4;
3731 configured_low_latency_capture_period_size = trial;
3732 }
3733 }
3734 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3735 trial = atoi(value);
3736 if (period_size_is_plausible_for_low_latency(trial)) {
3737 configured_low_latency_capture_period_size = trial;
3738 }
3739 }
3740
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003741 pthread_mutex_unlock(&adev_init_lock);
3742
Eric Laurent994a6932013-07-17 11:51:42 -07003743 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 return 0;
3745}
3746
3747static struct hw_module_methods_t hal_module_methods = {
3748 .open = adev_open,
3749};
3750
3751struct audio_module HAL_MODULE_INFO_SYM = {
3752 .common = {
3753 .tag = HARDWARE_MODULE_TAG,
3754 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3755 .hal_api_version = HARDWARE_HAL_API_VERSION,
3756 .id = AUDIO_HARDWARE_MODULE_ID,
3757 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003758 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 .methods = &hal_module_methods,
3760 },
3761};