blob: 32eec776097f75cad90fc3d809a207256ef4d2d0 [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
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800489 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
490 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
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800559 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
560 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) {
629 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
630 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);
661 /* Update the out_snd_device only before enabling the audio route */
662 if (switch_device[usecase->id] ) {
663 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800664 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530665 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700666 }
667 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 }
669}
670
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700671static void check_and_route_capture_usecases(struct audio_device *adev,
672 struct audio_usecase *uc_info,
673 snd_device_t snd_device)
674{
675 struct listnode *node;
676 struct audio_usecase *usecase;
677 bool switch_device[AUDIO_USECASE_MAX];
678 int i, num_uc_to_switch = 0;
679
680 /*
681 * This function is to make sure that all the active capture usecases
682 * are always routed to the same input sound device.
683 * For example, if audio-record and voice-call usecases are currently
684 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
685 * is received for voice call then we have to make sure that audio-record
686 * usecase is also switched to earpiece i.e. voice-dmic-ef,
687 * because of the limitation that two devices cannot be enabled
688 * at the same time if they share the same backend.
689 */
690 for (i = 0; i < AUDIO_USECASE_MAX; i++)
691 switch_device[i] = false;
692
693 list_for_each(node, &adev->usecase_list) {
694 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800695 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700696 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700697 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530698 (usecase->devices & AUDIO_DEVICE_OUT_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 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
874 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700875 select_devices(adev, adev->active_input->usecase);
876 }
877 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 } else if (usecase->type == PCM_CAPTURE) {
879 usecase->devices = usecase->stream.in->device;
880 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700881 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700882 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530883 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
884 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
885 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
886 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700887 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800888 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700889 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
890 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700892 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700893 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 }
895 }
896
897 if (out_snd_device == usecase->out_snd_device &&
898 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800899 return 0;
900 }
901
sangwoobc677242013-08-08 16:53:43 +0900902 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700903 out_snd_device, platform_get_snd_device_name(out_snd_device),
904 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800906 /*
907 * Limitation: While in call, to do a device switch we need to disable
908 * and enable both RX and TX devices though one of them is same as current
909 * device.
910 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700911 if ((usecase->type == VOICE_CALL) &&
912 (usecase->in_snd_device != SND_DEVICE_NONE) &&
913 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700914 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700915 /* Disable sidetone only if voice call already exists */
916 if (voice_is_call_state_active(adev))
917 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800918 }
919
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 /* Disable current sound devices */
921 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700922 disable_audio_route(adev, usecase);
923 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800924 }
925
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700926 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700927 disable_audio_route(adev, usecase);
928 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929 }
930
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800931 /* Applicable only on the targets that has external modem.
932 * New device information should be sent to modem before enabling
933 * the devices to reduce in-call device switch time.
934 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700935 if ((usecase->type == VOICE_CALL) &&
936 (usecase->in_snd_device != SND_DEVICE_NONE) &&
937 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800938 status = platform_switch_voice_call_enable_device_config(adev->platform,
939 out_snd_device,
940 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700941 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800942
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 /* Enable new sound devices */
944 if (out_snd_device != SND_DEVICE_NONE) {
945 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
946 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700947 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948 }
949
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 if (in_snd_device != SND_DEVICE_NONE) {
951 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700952 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700953 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954
Avinash Vaish71a8b972014-07-24 15:36:33 +0530955 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700956 status = platform_switch_voice_call_device_post(adev->platform,
957 out_snd_device,
958 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530959 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700960 /* Enable sidetone only if voice call already exists */
961 if (voice_is_call_state_active(adev))
962 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530963 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800964
sangwoo170731f2013-06-08 15:36:36 +0900965 usecase->in_snd_device = in_snd_device;
966 usecase->out_snd_device = out_snd_device;
967
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530968 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700969 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530970 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700971 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530972 usecase->stream.out->flags,
973 usecase->stream.out->format,
974 usecase->stream.out->sample_rate,
975 usecase->stream.out->bit_width,
976 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700977 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530978 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700979
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700980 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900981
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800982 /* Applicable only on the targets that has external modem.
983 * Enable device command should be sent to modem only after
984 * enabling voice call mixer controls
985 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700986 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800987 status = platform_switch_voice_call_usecase_route_post(adev->platform,
988 out_snd_device,
989 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530990 ALOGD("%s: done",__func__);
991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 return status;
993}
994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995static int stop_input_stream(struct stream_in *in)
996{
997 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998 struct audio_usecase *uc_info;
999 struct audio_device *adev = in->dev;
1000
Eric Laurentc8400632013-02-14 19:04:54 -08001001 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002
Eric Laurent994a6932013-07-17 11:51:42 -07001003 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001004 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005 uc_info = get_usecase_from_list(adev, in->usecase);
1006 if (uc_info == NULL) {
1007 ALOGE("%s: Could not find the usecase (%d) in the list",
1008 __func__, in->usecase);
1009 return -EINVAL;
1010 }
1011
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001012 /* Close in-call recording streams */
1013 voice_check_and_stop_incall_rec_usecase(adev, in);
1014
Eric Laurent150dbfe2013-02-27 14:31:02 -08001015 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001016 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017
1018 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001019 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001021 list_remove(&uc_info->list);
1022 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023
Eric Laurent994a6932013-07-17 11:51:42 -07001024 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 return ret;
1026}
1027
1028int start_input_stream(struct stream_in *in)
1029{
1030 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001031 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 struct audio_usecase *uc_info;
1033 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301034 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301036 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1037 if (get_usecase_from_list(adev, usecase) == NULL)
1038 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301039 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1040 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001041
Naresh Tanniru80659832014-06-04 18:17:56 +05301042
1043 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301044 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301045 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301046 goto error_config;
1047 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301048
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001049 /* Check if source matches incall recording usecase criteria */
1050 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1051 if (ret)
1052 goto error_config;
1053 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301054 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1055
1056 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1057 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1058 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1059 goto error_config;
1060 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001061
Eric Laurentb23d5282013-05-14 15:27:20 -07001062 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 if (in->pcm_device_id < 0) {
1064 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1065 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001066 ret = -EINVAL;
1067 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069
1070 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001072
1073 if (!uc_info) {
1074 ret = -ENOMEM;
1075 goto error_config;
1076 }
1077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 uc_info->id = in->usecase;
1079 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001080 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081 uc_info->devices = in->device;
1082 uc_info->in_snd_device = SND_DEVICE_NONE;
1083 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001085 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301086 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001087 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001088
Eric Laurentc8400632013-02-14 19:04:54 -08001089 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001090 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1091
1092 unsigned int flags = PCM_IN;
1093 unsigned int pcm_open_retry_count = 0;
1094
1095 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1096 flags |= PCM_MMAP | PCM_NOIRQ;
1097 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1098 }
1099
1100 while (1) {
1101 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1102 flags, &in->config);
1103 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1104 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1105 if (in->pcm != NULL) {
1106 pcm_close(in->pcm);
1107 in->pcm = NULL;
1108 }
1109 if (pcm_open_retry_count-- == 0) {
1110 ret = -EIO;
1111 goto error_open;
1112 }
1113 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1114 continue;
1115 }
1116 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301118 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301119
Eric Laurent994a6932013-07-17 11:51:42 -07001120 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001121 return ret;
1122
1123error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301125 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001126
1127error_config:
1128 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001130
1131 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001132}
1133
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001134/* must be called with out->lock locked */
1135static int send_offload_cmd_l(struct stream_out* out, int command)
1136{
1137 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1138
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001139 if (!cmd) {
1140 ALOGE("failed to allocate mem for command 0x%x", command);
1141 return -ENOMEM;
1142 }
1143
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001144 ALOGVV("%s %d", __func__, command);
1145
1146 cmd->cmd = command;
1147 list_add_tail(&out->offload_cmd_list, &cmd->node);
1148 pthread_cond_signal(&out->offload_cond);
1149 return 0;
1150}
1151
1152/* must be called iwth out->lock locked */
1153static void stop_compressed_output_l(struct stream_out *out)
1154{
1155 out->offload_state = OFFLOAD_STATE_IDLE;
1156 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001157 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001158 if (out->compr != NULL) {
1159 compress_stop(out->compr);
1160 while (out->offload_thread_blocked) {
1161 pthread_cond_wait(&out->cond, &out->lock);
1162 }
1163 }
1164}
1165
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001166bool is_offload_usecase(audio_usecase_t uc_id)
1167{
1168 unsigned int i;
1169 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1170 if (uc_id == offload_usecases[i])
1171 return true;
1172 }
1173 return false;
1174}
1175
1176static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1177{
1178 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1179 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1180 char value[PROPERTY_VALUE_MAX] = {0};
1181
1182 property_get("audio.offload.multiple.enabled", value, NULL);
1183 if (!(atoi(value) || !strncmp("true", value, 4)))
1184 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1185
1186 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1187 for (i = 0; i < num_usecase; i++) {
1188 if (!(adev->offload_usecases_state & (0x1<<i))) {
1189 adev->offload_usecases_state |= 0x1 << i;
1190 ret = offload_usecases[i];
1191 break;
1192 }
1193 }
1194 ALOGV("%s: offload usecase is %d", __func__, ret);
1195 return ret;
1196}
1197
1198static void free_offload_usecase(struct audio_device *adev,
1199 audio_usecase_t uc_id)
1200{
1201 unsigned int i;
1202 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1203 if (offload_usecases[i] == uc_id) {
1204 adev->offload_usecases_state &= ~(0x1<<i);
1205 break;
1206 }
1207 }
1208 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1209}
1210
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001211static void *offload_thread_loop(void *context)
1212{
1213 struct stream_out *out = (struct stream_out *) context;
1214 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001215 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001216
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1218 set_sched_policy(0, SP_FOREGROUND);
1219 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1220
1221 ALOGV("%s", __func__);
1222 pthread_mutex_lock(&out->lock);
1223 for (;;) {
1224 struct offload_cmd *cmd = NULL;
1225 stream_callback_event_t event;
1226 bool send_callback = false;
1227
1228 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1229 __func__, list_empty(&out->offload_cmd_list),
1230 out->offload_state);
1231 if (list_empty(&out->offload_cmd_list)) {
1232 ALOGV("%s SLEEPING", __func__);
1233 pthread_cond_wait(&out->offload_cond, &out->lock);
1234 ALOGV("%s RUNNING", __func__);
1235 continue;
1236 }
1237
1238 item = list_head(&out->offload_cmd_list);
1239 cmd = node_to_item(item, struct offload_cmd, node);
1240 list_remove(item);
1241
1242 ALOGVV("%s STATE %d CMD %d out->compr %p",
1243 __func__, out->offload_state, cmd->cmd, out->compr);
1244
1245 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1246 free(cmd);
1247 break;
1248 }
1249
1250 if (out->compr == NULL) {
1251 ALOGE("%s: Compress handle is NULL", __func__);
1252 pthread_cond_signal(&out->cond);
1253 continue;
1254 }
1255 out->offload_thread_blocked = true;
1256 pthread_mutex_unlock(&out->lock);
1257 send_callback = false;
1258 switch(cmd->cmd) {
1259 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001260 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001261 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001262 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001263 send_callback = true;
1264 event = STREAM_CBK_EVENT_WRITE_READY;
1265 break;
1266 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001267 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301268 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001269 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301270 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001271 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301272 if (ret < 0)
1273 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301274 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301275 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001276 compress_drain(out->compr);
1277 else
1278 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301279 if (ret != -ENETRESET) {
1280 send_callback = true;
1281 event = STREAM_CBK_EVENT_DRAIN_READY;
1282 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1283 } else
1284 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001285 break;
1286 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001287 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001288 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001289 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 send_callback = true;
1291 event = STREAM_CBK_EVENT_DRAIN_READY;
1292 break;
1293 default:
1294 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1295 break;
1296 }
1297 pthread_mutex_lock(&out->lock);
1298 out->offload_thread_blocked = false;
1299 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001300 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001301 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001302 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001303 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 free(cmd);
1305 }
1306
1307 pthread_cond_signal(&out->cond);
1308 while (!list_empty(&out->offload_cmd_list)) {
1309 item = list_head(&out->offload_cmd_list);
1310 list_remove(item);
1311 free(node_to_item(item, struct offload_cmd, node));
1312 }
1313 pthread_mutex_unlock(&out->lock);
1314
1315 return NULL;
1316}
1317
1318static int create_offload_callback_thread(struct stream_out *out)
1319{
1320 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1321 list_init(&out->offload_cmd_list);
1322 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1323 offload_thread_loop, out);
1324 return 0;
1325}
1326
1327static int destroy_offload_callback_thread(struct stream_out *out)
1328{
1329 pthread_mutex_lock(&out->lock);
1330 stop_compressed_output_l(out);
1331 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1332
1333 pthread_mutex_unlock(&out->lock);
1334 pthread_join(out->offload_thread, (void **) NULL);
1335 pthread_cond_destroy(&out->offload_cond);
1336
1337 return 0;
1338}
1339
Eric Laurent07eeafd2013-10-06 12:52:49 -07001340static bool allow_hdmi_channel_config(struct audio_device *adev)
1341{
1342 struct listnode *node;
1343 struct audio_usecase *usecase;
1344 bool ret = true;
1345
1346 list_for_each(node, &adev->usecase_list) {
1347 usecase = node_to_item(node, struct audio_usecase, list);
1348 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1349 /*
1350 * If voice call is already existing, do not proceed further to avoid
1351 * disabling/enabling both RX and TX devices, CSD calls, etc.
1352 * Once the voice call done, the HDMI channels can be configured to
1353 * max channels of remaining use cases.
1354 */
1355 if (usecase->id == USECASE_VOICE_CALL) {
1356 ALOGD("%s: voice call is active, no change in HDMI channels",
1357 __func__);
1358 ret = false;
1359 break;
1360 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1361 ALOGD("%s: multi channel playback is active, "
1362 "no change in HDMI channels", __func__);
1363 ret = false;
1364 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001365 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001366 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001367 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1368 ", no change in HDMI channels", __func__,
1369 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001370 ret = false;
1371 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001372 }
1373 }
1374 }
1375 return ret;
1376}
1377
1378static int check_and_set_hdmi_channels(struct audio_device *adev,
1379 unsigned int channels)
1380{
1381 struct listnode *node;
1382 struct audio_usecase *usecase;
1383
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001384 unsigned int supported_channels = platform_edid_get_max_channels(
1385 adev->platform);
1386 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 /* Check if change in HDMI channel config is allowed */
1388 if (!allow_hdmi_channel_config(adev))
1389 return 0;
1390
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001391 if (channels > supported_channels)
1392 channels = supported_channels;
1393
Eric Laurent07eeafd2013-10-06 12:52:49 -07001394 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001395 ALOGD("%s: Requested channels are same as current channels(%d)",
1396 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001397 return 0;
1398 }
1399
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001400 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001402 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001403 adev->cur_hdmi_channels = channels;
1404
1405 /*
1406 * Deroute all the playback streams routed to HDMI so that
1407 * the back end is deactivated. Note that backend will not
1408 * be deactivated if any one stream is connected to it.
1409 */
1410 list_for_each(node, &adev->usecase_list) {
1411 usecase = node_to_item(node, struct audio_usecase, list);
1412 if (usecase->type == PCM_PLAYBACK &&
1413 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001414 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001415 }
1416 }
1417
1418 /*
1419 * Enable all the streams disabled above. Now the HDMI backend
1420 * will be activated with new channel configuration
1421 */
1422 list_for_each(node, &adev->usecase_list) {
1423 usecase = node_to_item(node, struct audio_usecase, list);
1424 if (usecase->type == PCM_PLAYBACK &&
1425 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001426 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001427 }
1428 }
1429
1430 return 0;
1431}
1432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433static int stop_output_stream(struct stream_out *out)
1434{
1435 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 struct audio_usecase *uc_info;
1437 struct audio_device *adev = out->dev;
1438
Eric Laurent994a6932013-07-17 11:51:42 -07001439 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001440 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441 uc_info = get_usecase_from_list(adev, out->usecase);
1442 if (uc_info == NULL) {
1443 ALOGE("%s: Could not find the usecase (%d) in the list",
1444 __func__, out->usecase);
1445 return -EINVAL;
1446 }
1447
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001448 if (is_offload_usecase(out->usecase) &&
1449 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001450 if (adev->visualizer_stop_output != NULL)
1451 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001452
1453 audio_extn_dts_remove_state_notifier_node(out->usecase);
1454
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001455 if (adev->offload_effects_stop_output != NULL)
1456 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1457 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001458
Eric Laurent150dbfe2013-02-27 14:31:02 -08001459 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001460 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461
1462 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001463 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001465 list_remove(&uc_info->list);
1466 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001468 if (is_offload_usecase(out->usecase) &&
1469 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1470 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1471 ALOGV("Disable passthrough , reset mixer to pcm");
1472 /* NO_PASSTHROUGH */
1473 out->compr_config.codec->compr_passthr = 0;
1474 audio_extn_dolby_set_hdmi_config(adev, out);
1475 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1476 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001477 /* Must be called after removing the usecase from list */
1478 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1479 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1480
Eric Laurent994a6932013-07-17 11:51:42 -07001481 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 return ret;
1483}
1484
1485int start_output_stream(struct stream_out *out)
1486{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001488 int sink_channels = 0;
1489 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 struct audio_usecase *uc_info;
1491 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301492 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001494 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1495 ret = -EINVAL;
1496 goto error_config;
1497 }
1498
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301499 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1500 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1501 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301502
Naresh Tanniru80659832014-06-04 18:17:56 +05301503 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301504 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301505 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301506 goto error_config;
1507 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301508
Eric Laurentb23d5282013-05-14 15:27:20 -07001509 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 if (out->pcm_device_id < 0) {
1511 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1512 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001513 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001514 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515 }
1516
1517 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001518
1519 if (!uc_info) {
1520 ret = -ENOMEM;
1521 goto error_config;
1522 }
1523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 uc_info->id = out->usecase;
1525 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001526 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 uc_info->devices = out->devices;
1528 uc_info->in_snd_device = SND_DEVICE_NONE;
1529 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001530 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001531 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001532 if (is_offload_usecase(out->usecase)) {
1533 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001534 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1535 }
1536 }
Mingming Yin9c041392014-05-01 15:37:31 -07001537 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1538 if (!strncmp("true", prop_value, 4)) {
1539 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001540 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1541 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001542 check_and_set_hdmi_channels(adev, sink_channels);
1543 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001544 if (is_offload_usecase(out->usecase)) {
1545 unsigned int ch_count = out->compr_config.codec->ch_in;
1546 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1547 /* backend channel config for passthrough stream is stereo */
1548 ch_count = 2;
1549 check_and_set_hdmi_channels(adev, ch_count);
1550 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001551 check_and_set_hdmi_channels(adev, out->config.channels);
1552 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001553 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001554 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001555 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 select_devices(adev, out->usecase);
1558
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001559 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1560 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001561 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001562 unsigned int flags = PCM_OUT;
1563 unsigned int pcm_open_retry_count = 0;
1564 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1565 flags |= PCM_MMAP | PCM_NOIRQ;
1566 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1567 } else
1568 flags |= PCM_MONOTONIC;
1569
1570 while (1) {
1571 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1572 flags, &out->config);
1573 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1574 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1575 if (out->pcm != NULL) {
1576 pcm_close(out->pcm);
1577 out->pcm = NULL;
1578 }
1579 if (pcm_open_retry_count-- == 0) {
1580 ret = -EIO;
1581 goto error_open;
1582 }
1583 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1584 continue;
1585 }
1586 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001587 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001588 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1589 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001591 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1592 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001594 out->compr = compress_open(adev->snd_card,
1595 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596 COMPRESS_IN, &out->compr_config);
1597 if (out->compr && !is_compress_ready(out->compr)) {
1598 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1599 compress_close(out->compr);
1600 out->compr = NULL;
1601 ret = -EIO;
1602 goto error_open;
1603 }
1604 if (out->offload_callback)
1605 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001606
Fred Oh3f43e742015-03-04 18:42:34 -08001607 /* Since small bufs uses blocking writes, a write will be blocked
1608 for the default max poll time (20s) in the event of an SSR.
1609 Reduce the poll time to observe and deal with SSR faster.
1610 */
1611 if (out->use_small_bufs) {
1612 compress_set_max_poll_wait(out->compr, 1000);
1613 }
1614
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001615 audio_extn_dts_create_state_notifier_node(out->usecase);
1616 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1617 popcount(out->channel_mask),
1618 out->playback_started);
1619
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001620#ifdef DS1_DOLBY_DDP_ENABLED
1621 if (audio_extn_is_dolby_format(out->format))
1622 audio_extn_dolby_send_ddp_endp_params(adev);
1623#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001624 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1625 if (adev->visualizer_start_output != NULL)
1626 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1627 if (adev->offload_effects_start_output != NULL)
1628 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001629 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631 }
Eric Laurent994a6932013-07-17 11:51:42 -07001632 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001634error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001636error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001637 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638}
1639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640static int check_input_parameters(uint32_t sample_rate,
1641 audio_format_t format,
1642 int channel_count)
1643{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001644 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001646 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001647 !voice_extn_compress_voip_is_format_supported(format) &&
1648 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001649
1650 switch (channel_count) {
1651 case 1:
1652 case 2:
1653 case 6:
1654 break;
1655 default:
1656 ret = -EINVAL;
1657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
1659 switch (sample_rate) {
1660 case 8000:
1661 case 11025:
1662 case 12000:
1663 case 16000:
1664 case 22050:
1665 case 24000:
1666 case 32000:
1667 case 44100:
1668 case 48000:
1669 break;
1670 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001671 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672 }
1673
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001674 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001675}
1676
1677static size_t get_input_buffer_size(uint32_t sample_rate,
1678 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001679 int channel_count,
1680 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001681{
1682 size_t size = 0;
1683
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001684 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1685 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001687 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001688 if (is_low_latency)
1689 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001690 /* ToDo: should use frame_size computed based on the format and
1691 channel_count here. */
1692 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001693
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001694 /* make sure the size is multiple of 32 bytes
1695 * At 48 kHz mono 16-bit PCM:
1696 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1697 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1698 */
1699 size += 0x1f;
1700 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001701
1702 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703}
1704
1705static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1706{
1707 struct stream_out *out = (struct stream_out *)stream;
1708
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001709 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710}
1711
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001712static int out_set_sample_rate(struct audio_stream *stream __unused,
1713 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714{
1715 return -ENOSYS;
1716}
1717
1718static size_t out_get_buffer_size(const struct audio_stream *stream)
1719{
1720 struct stream_out *out = (struct stream_out *)stream;
1721
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001722 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001724 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1725 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001727 return out->config.period_size *
1728 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729}
1730
1731static uint32_t out_get_channels(const struct audio_stream *stream)
1732{
1733 struct stream_out *out = (struct stream_out *)stream;
1734
1735 return out->channel_mask;
1736}
1737
1738static audio_format_t out_get_format(const struct audio_stream *stream)
1739{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740 struct stream_out *out = (struct stream_out *)stream;
1741
1742 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743}
1744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001745static int out_set_format(struct audio_stream *stream __unused,
1746 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747{
1748 return -ENOSYS;
1749}
1750
1751static int out_standby(struct audio_stream *stream)
1752{
1753 struct stream_out *out = (struct stream_out *)stream;
1754 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301756 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1757 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001758 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1759 /* Ignore standby in case of voip call because the voip output
1760 * stream is closed in adev_close_output_stream()
1761 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301762 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001763 return 0;
1764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001768 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001770 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 if (out->pcm) {
1772 pcm_close(out->pcm);
1773 out->pcm = NULL;
1774 }
1775 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001776 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001778 out->gapless_mdata.encoder_delay = 0;
1779 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 if (out->compr != NULL) {
1781 compress_close(out->compr);
1782 out->compr = NULL;
1783 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001784 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001786 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 }
1788 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001789 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 return 0;
1791}
1792
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001793static int out_dump(const struct audio_stream *stream __unused,
1794 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795{
1796 return 0;
1797}
1798
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001799static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1800{
1801 int ret = 0;
1802 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001803 bool is_meta_data_params = false;
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 }
1816 out->send_new_metadata = 1;
1817 }
1818
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301819 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001820
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001821 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1822 if(ret >= 0)
1823 is_meta_data_params = true;
1824 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301825 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001826 is_meta_data_params = true;
1827 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301828 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001829 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1831 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001832 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301833 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1836 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001837 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301838 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001839 }
1840
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001841 if(!is_meta_data_params) {
1842 ALOGV("%s: Not gapless meta data params", __func__);
1843 return 0;
1844 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001845 out->send_new_metadata = 1;
1846 ALOGV("%s new encoder delay %u and padding %u", __func__,
1847 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1848
1849 return 0;
1850}
1851
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001852static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1853{
1854 return out == adev->primary_output || out == adev->voice_tx_output;
1855}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1858{
1859 struct stream_out *out = (struct stream_out *)stream;
1860 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001861 struct audio_usecase *usecase;
1862 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 struct str_parms *parms;
1864 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001865 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001866 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867
sangwoobc677242013-08-08 16:53:43 +09001868 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301871 if (!parms)
1872 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001873 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1874 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001877 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301880 * When HDMI cable is unplugged/usb hs is disconnected the
1881 * music playback is paused and the policy manager sends routing=0
1882 * But the audioflingercontinues to write data until standby time
1883 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001884 * Avoid this by routing audio to speaker until standby.
1885 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301886 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1887 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001889 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1890 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001891 }
1892
1893 /*
1894 * select_devices() call below switches all the usecases on the same
1895 * backend to the new device. Refer to check_usecases_codec_backend() in
1896 * the select_devices(). But how do we undo this?
1897 *
1898 * For example, music playback is active on headset (deep-buffer usecase)
1899 * and if we go to ringtones and select a ringtone, low-latency usecase
1900 * will be started on headset+speaker. As we can't enable headset+speaker
1901 * and headset devices at the same time, select_devices() switches the music
1902 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1903 * So when the ringtone playback is completed, how do we undo the same?
1904 *
1905 * We are relying on the out_set_parameters() call on deep-buffer output,
1906 * once the ringtone playback is ended.
1907 * NOTE: We should not check if the current devices are same as new devices.
1908 * Because select_devices() must be called to switch back the music
1909 * playback to headset.
1910 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001911 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001912 out->devices = val;
1913
1914 if (!out->standby)
1915 select_devices(adev, out->usecase);
1916
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001917 if (output_drives_call(adev, out)) {
1918 if(!voice_is_in_call(adev)) {
1919 if (adev->mode == AUDIO_MODE_IN_CALL) {
1920 adev->current_call_output = out;
1921 ret = voice_start_call(adev);
1922 }
1923 } else {
1924 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001925 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001926 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001927 }
1928 }
1929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001931 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001933
1934 if (out == adev->primary_output) {
1935 pthread_mutex_lock(&adev->lock);
1936 audio_extn_set_parameters(adev, parms);
1937 pthread_mutex_unlock(&adev->lock);
1938 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001939 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001940 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001941 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001942
1943 audio_extn_dts_create_state_notifier_node(out->usecase);
1944 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1945 popcount(out->channel_mask),
1946 out->playback_started);
1947
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001948 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001949 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301952error:
Eric Laurent994a6932013-07-17 11:51:42 -07001953 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 return ret;
1955}
1956
1957static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1958{
1959 struct stream_out *out = (struct stream_out *)stream;
1960 struct str_parms *query = str_parms_create_str(keys);
1961 char *str;
1962 char value[256];
1963 struct str_parms *reply = str_parms_create();
1964 size_t i, j;
1965 int ret;
1966 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001967
1968 if (!query || !reply) {
1969 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1970 return NULL;
1971 }
1972
Eric Laurent994a6932013-07-17 11:51:42 -07001973 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1975 if (ret >= 0) {
1976 value[0] = '\0';
1977 i = 0;
1978 while (out->supported_channel_masks[i] != 0) {
1979 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1980 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1981 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001982 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001984 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001985 first = false;
1986 break;
1987 }
1988 }
1989 i++;
1990 }
1991 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1992 str = str_parms_to_str(reply);
1993 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001994 voice_extn_out_get_parameters(out, query, reply);
1995 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001996 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001997 free(str);
1998 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001999 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002001
2002 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2003 if (ret >= 0) {
2004 value[0] = '\0';
2005 i = 0;
2006 first = true;
2007 while (out->supported_formats[i] != 0) {
2008 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2009 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2010 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002011 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002012 }
2013 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2014 first = false;
2015 break;
2016 }
2017 }
2018 i++;
2019 }
2020 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2021 str = str_parms_to_str(reply);
2022 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 str_parms_destroy(query);
2024 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002025 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 return str;
2027}
2028
2029static uint32_t out_get_latency(const struct audio_stream_out *stream)
2030{
2031 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002032 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Alexy Josephaa54c872014-12-03 02:46:47 -08002034 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002035 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002036 } else {
2037 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002039 }
2040
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302041 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002042 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043}
2044
2045static int out_set_volume(struct audio_stream_out *stream, float left,
2046 float right)
2047{
Eric Laurenta9024de2013-04-04 09:19:12 -07002048 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049 int volume[2];
2050
Eric Laurenta9024de2013-04-04 09:19:12 -07002051 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2052 /* only take left channel into account: the API is for stereo anyway */
2053 out->muted = (left == 0.0f);
2054 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002055 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002056 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2057 /*
2058 * Set mute or umute on HDMI passthrough stream.
2059 * Only take left channel into account.
2060 * Mute is 0 and unmute 1
2061 */
2062 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2063 } else {
2064 char mixer_ctl_name[128];
2065 struct audio_device *adev = out->dev;
2066 struct mixer_ctl *ctl;
2067 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002068 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002070 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2071 "Compress Playback %d Volume", pcm_device_id);
2072 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2073 if (!ctl) {
2074 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2075 __func__, mixer_ctl_name);
2076 return -EINVAL;
2077 }
2078 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2079 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2080 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2081 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002083 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085 return -ENOSYS;
2086}
2087
2088static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2089 size_t bytes)
2090{
2091 struct stream_out *out = (struct stream_out *)stream;
2092 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302093 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002094 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302097
Naresh Tanniru80659832014-06-04 18:17:56 +05302098 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002099 // increase written size during SSR to avoid mismatch
2100 // with the written frames count in AF
2101 if (!is_offload_usecase(out->usecase))
2102 out->written += bytes / (out->config.channels * sizeof(short));
2103
Naresh Tanniru80659832014-06-04 18:17:56 +05302104 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302105 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302106 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302107 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002108 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302109 //during SSR for compress usecase we should return error to flinger
2110 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2111 pthread_mutex_unlock(&out->lock);
2112 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302113 }
2114 }
2115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002117 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002118 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002119 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2120 ret = voice_extn_compress_voip_start_output_stream(out);
2121 else
2122 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002123 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002126 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 goto exit;
2128 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002131 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002132 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002133 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002134 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002135 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2136 out->send_new_metadata = 0;
2137 }
2138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302140 if (ret < 0)
2141 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002142 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002143 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302144 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302146 } else if (-ENETRESET == ret) {
2147 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2148 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2149 pthread_mutex_unlock(&out->lock);
2150 out_standby(&out->stream.common);
2151 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302153 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002155 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 out->playback_started = 1;
2157 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002158
2159 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2160 popcount(out->channel_mask),
2161 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 }
2163 pthread_mutex_unlock(&out->lock);
2164 return ret;
2165 } else {
2166 if (out->pcm) {
2167 if (out->muted)
2168 memset((void *)buffer, 0, bytes);
2169 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002170 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2171 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2172 else
2173 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302174 if (ret < 0)
2175 ret = -errno;
2176 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002177 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 }
2180
2181exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302182 /* ToDo: There may be a corner case when SSR happens back to back during
2183 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302184 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302185 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302186 }
2187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 pthread_mutex_unlock(&out->lock);
2189
2190 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002191 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002192 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302193 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302194 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302195 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302196 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302197 out->standby = true;
2198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002200 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302201 out_get_sample_rate(&out->stream.common));
2202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 }
2204 return bytes;
2205}
2206
2207static int out_get_render_position(const struct audio_stream_out *stream,
2208 uint32_t *dsp_frames)
2209{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302211 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002212
2213 if (dsp_frames == NULL)
2214 return -EINVAL;
2215
2216 *dsp_frames = 0;
2217 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002218 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 pthread_mutex_lock(&out->lock);
2220 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302221 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302223 if (ret < 0)
2224 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 ALOGVV("%s rendered frames %d sample_rate %d",
2226 __func__, *dsp_frames, out->sample_rate);
2227 }
2228 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 if (-ENETRESET == ret) {
2230 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2231 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2232 return -EINVAL;
2233 } else if(ret < 0) {
2234 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2235 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302236 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2237 /*
2238 * Handle corner case where compress session is closed during SSR
2239 * and timestamp is queried
2240 */
2241 ALOGE(" ERROR: sound card not active, return error");
2242 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302243 } else {
2244 return 0;
2245 }
Zhou Song32a556e2015-05-05 10:46:56 +08002246 } else if (audio_is_linear_pcm(out->format)) {
2247 *dsp_frames = out->written;
2248 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 } else
2250 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251}
2252
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002253static int out_add_audio_effect(const struct audio_stream *stream __unused,
2254 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255{
2256 return 0;
2257}
2258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002259static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2260 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261{
2262 return 0;
2263}
2264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002265static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2266 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267{
2268 return -EINVAL;
2269}
2270
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002271static int out_get_presentation_position(const struct audio_stream_out *stream,
2272 uint64_t *frames, struct timespec *timestamp)
2273{
2274 struct stream_out *out = (struct stream_out *)stream;
2275 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002276 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002277
2278 pthread_mutex_lock(&out->lock);
2279
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002280 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002281 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302282 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002283 &out->sample_rate);
2284 ALOGVV("%s rendered frames %ld sample_rate %d",
2285 __func__, dsp_frames, out->sample_rate);
2286 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302287 if (ret < 0)
2288 ret = -errno;
2289 if (-ENETRESET == ret) {
2290 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2291 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2292 ret = -EINVAL;
2293 } else
2294 ret = 0;
2295
Eric Laurent949a0892013-09-20 09:20:13 -07002296 /* this is the best we can do */
2297 clock_gettime(CLOCK_MONOTONIC, timestamp);
2298 }
2299 } else {
2300 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002301 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002302 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2303 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002304 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002305 // This adjustment accounts for buffering after app processor.
2306 // It is based on estimated DSP latency per use case, rather than exact.
2307 signed_frames -=
2308 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2309
Eric Laurent949a0892013-09-20 09:20:13 -07002310 // It would be unusual for this value to be negative, but check just in case ...
2311 if (signed_frames >= 0) {
2312 *frames = signed_frames;
2313 ret = 0;
2314 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002315 }
2316 }
2317 }
2318
2319 pthread_mutex_unlock(&out->lock);
2320
2321 return ret;
2322}
2323
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324static int out_set_callback(struct audio_stream_out *stream,
2325 stream_callback_t callback, void *cookie)
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328
2329 ALOGV("%s", __func__);
2330 pthread_mutex_lock(&out->lock);
2331 out->offload_callback = callback;
2332 out->offload_cookie = cookie;
2333 pthread_mutex_unlock(&out->lock);
2334 return 0;
2335}
2336
2337static int out_pause(struct audio_stream_out* stream)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340 int status = -ENOSYS;
2341 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002342 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002343 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 pthread_mutex_lock(&out->lock);
2345 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302346 struct audio_device *adev = out->dev;
2347 int snd_scard_state = get_snd_card_state(adev);
2348
2349 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2350 status = compress_pause(out->compr);
2351
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002353
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302354 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002355 audio_extn_dts_notify_playback_state(out->usecase, 0,
2356 out->sample_rate, popcount(out->channel_mask),
2357 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 }
2359 pthread_mutex_unlock(&out->lock);
2360 }
2361 return status;
2362}
2363
2364static int out_resume(struct audio_stream_out* stream)
2365{
2366 struct stream_out *out = (struct stream_out *)stream;
2367 int status = -ENOSYS;
2368 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002369 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002370 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 status = 0;
2372 pthread_mutex_lock(&out->lock);
2373 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302374 struct audio_device *adev = out->dev;
2375 int snd_scard_state = get_snd_card_state(adev);
2376
2377 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2378 status = compress_resume(out->compr);
2379
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002381
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302382 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002383 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2384 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 }
2386 pthread_mutex_unlock(&out->lock);
2387 }
2388 return status;
2389}
2390
2391static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
2394 int status = -ENOSYS;
2395 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002396 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 pthread_mutex_lock(&out->lock);
2398 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2399 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2400 else
2401 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2402 pthread_mutex_unlock(&out->lock);
2403 }
2404 return status;
2405}
2406
2407static int out_flush(struct audio_stream_out* stream)
2408{
2409 struct stream_out *out = (struct stream_out *)stream;
2410 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002411 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002412 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 pthread_mutex_lock(&out->lock);
2414 stop_compressed_output_l(out);
2415 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002416 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002417 return 0;
2418 }
2419 return -ENOSYS;
2420}
2421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422/** audio_stream_in implementation **/
2423static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426
2427 return in->config.rate;
2428}
2429
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002430static int in_set_sample_rate(struct audio_stream *stream __unused,
2431 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 return -ENOSYS;
2434}
2435
2436static size_t in_get_buffer_size(const struct audio_stream *stream)
2437{
2438 struct stream_in *in = (struct stream_in *)stream;
2439
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2441 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002442 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2443 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002444
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002445 return in->config.period_size *
2446 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447}
2448
2449static uint32_t in_get_channels(const struct audio_stream *stream)
2450{
2451 struct stream_in *in = (struct stream_in *)stream;
2452
2453 return in->channel_mask;
2454}
2455
2456static audio_format_t in_get_format(const struct audio_stream *stream)
2457{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002458 struct stream_in *in = (struct stream_in *)stream;
2459
2460 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461}
2462
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002463static int in_set_format(struct audio_stream *stream __unused,
2464 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465{
2466 return -ENOSYS;
2467}
2468
2469static int in_standby(struct audio_stream *stream)
2470{
2471 struct stream_in *in = (struct stream_in *)stream;
2472 struct audio_device *adev = in->dev;
2473 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302474 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2475 stream, in->usecase, use_case_table[in->usecase]);
2476
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2478 /* Ignore standby in case of voip call because the voip input
2479 * stream is closed in adev_close_input_stream()
2480 */
2481 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2482 return status;
2483 }
2484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002486 if (!in->standby && in->is_st_session) {
2487 ALOGD("%s: sound trigger pcm stop lab", __func__);
2488 audio_extn_sound_trigger_stop_lab(in);
2489 in->standby = 1;
2490 }
2491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002493 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002495 if (in->pcm) {
2496 pcm_close(in->pcm);
2497 in->pcm = NULL;
2498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002500 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 }
2502 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002503 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 return status;
2505}
2506
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002507static int in_dump(const struct audio_stream *stream __unused,
2508 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509{
2510 return 0;
2511}
2512
2513static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2514{
2515 struct stream_in *in = (struct stream_in *)stream;
2516 struct audio_device *adev = in->dev;
2517 struct str_parms *parms;
2518 char *str;
2519 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002520 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302522 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 parms = str_parms_create_str(kvpairs);
2524
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302525 if (!parms)
2526 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002528 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002529
2530 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2531 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 val = atoi(value);
2533 /* no audio source uses val == 0 */
2534 if ((in->source != val) && (val != 0)) {
2535 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002536 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2537 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2538 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2539 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002540 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002541 err = voice_extn_compress_voip_open_input_stream(in);
2542 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002543 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002544 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002545 }
2546 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 }
2548 }
2549
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002550 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2551 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002553 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 in->device = val;
2555 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002556 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002557 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 }
2559 }
2560
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002561done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002563 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564
2565 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302566error:
Eric Laurent994a6932013-07-17 11:51:42 -07002567 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 return ret;
2569}
2570
2571static char* in_get_parameters(const struct audio_stream *stream,
2572 const char *keys)
2573{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 struct stream_in *in = (struct stream_in *)stream;
2575 struct str_parms *query = str_parms_create_str(keys);
2576 char *str;
2577 char value[256];
2578 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002579
2580 if (!query || !reply) {
2581 ALOGE("in_get_parameters: failed to create query or reply");
2582 return NULL;
2583 }
2584
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002585 ALOGV("%s: enter: keys - %s", __func__, keys);
2586
2587 voice_extn_in_get_parameters(in, query, reply);
2588
2589 str = str_parms_to_str(reply);
2590 str_parms_destroy(query);
2591 str_parms_destroy(reply);
2592
2593 ALOGV("%s: exit: returns - %s", __func__, str);
2594 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595}
2596
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002597static int in_set_gain(struct audio_stream_in *stream __unused,
2598 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599{
2600 return 0;
2601}
2602
2603static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2604 size_t bytes)
2605{
2606 struct stream_in *in = (struct stream_in *)stream;
2607 struct audio_device *adev = in->dev;
2608 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302609 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302612
2613 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302614 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302615 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302616 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302617 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002618 } else {
2619 if (in->is_st_session && !in->is_st_session_active) {
2620 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2621 ret= -EIO;;
2622 goto exit;
2623 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624 }
2625 }
2626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002628 if (!in->is_st_session) {
2629 pthread_mutex_lock(&adev->lock);
2630 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2631 ret = voice_extn_compress_voip_start_input_stream(in);
2632 else
2633 ret = start_input_stream(in);
2634 pthread_mutex_unlock(&adev->lock);
2635 if (ret != 0) {
2636 goto exit;
2637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 }
2639 in->standby = 0;
2640 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641
2642 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002643 if (audio_extn_ssr_get_enabled() &&
2644 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002645 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002646 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2647 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002648 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2649 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002650 else
2651 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302652 if (ret < 0)
2653 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 }
2655
2656 /*
2657 * Instead of writing zeroes here, we could trust the hardware
2658 * to always provide zeroes when muted.
2659 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302660 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2661 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 memset(buffer, 0, bytes);
2663
2664exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302665 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302666 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302667 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002668 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2669 session reading on LAB data. In this case do not set sound card state
2670 offline, instead mark this sound trigger session inactive to avoid
2671 further reading of LAB data from CPE driver. Marking the session
2672 inactive handles both CPE and ADSP SSR for sound trigger session */
2673 if (!in->is_st_session)
2674 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2675 else
2676 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302677 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 pthread_mutex_unlock(&in->lock);
2679
2680 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302681 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302682 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302683 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302684 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302685 in->standby = true;
2686 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302687 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002689 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002690 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302691 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 }
2693 return bytes;
2694}
2695
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002696static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697{
2698 return 0;
2699}
2700
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002701static int add_remove_audio_effect(const struct audio_stream *stream,
2702 effect_handle_t effect,
2703 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002705 struct stream_in *in = (struct stream_in *)stream;
2706 int status = 0;
2707 effect_descriptor_t desc;
2708
2709 status = (*effect)->get_descriptor(effect, &desc);
2710 if (status != 0)
2711 return status;
2712
2713 pthread_mutex_lock(&in->lock);
2714 pthread_mutex_lock(&in->dev->lock);
2715 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2716 in->enable_aec != enable &&
2717 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2718 in->enable_aec = enable;
2719 if (!in->standby)
2720 select_devices(in->dev, in->usecase);
2721 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002722 if (in->enable_ns != enable &&
2723 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2724 in->enable_ns = enable;
2725 if (!in->standby)
2726 select_devices(in->dev, in->usecase);
2727 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002728 pthread_mutex_unlock(&in->dev->lock);
2729 pthread_mutex_unlock(&in->lock);
2730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 return 0;
2732}
2733
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002734static int in_add_audio_effect(const struct audio_stream *stream,
2735 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736{
Eric Laurent994a6932013-07-17 11:51:42 -07002737 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002738 return add_remove_audio_effect(stream, effect, true);
2739}
2740
2741static int in_remove_audio_effect(const struct audio_stream *stream,
2742 effect_handle_t effect)
2743{
Eric Laurent994a6932013-07-17 11:51:42 -07002744 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002745 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746}
2747
2748static int adev_open_output_stream(struct audio_hw_device *dev,
2749 audio_io_handle_t handle,
2750 audio_devices_t devices,
2751 audio_output_flags_t flags,
2752 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002753 struct audio_stream_out **stream_out,
2754 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755{
2756 struct audio_device *adev = (struct audio_device *)dev;
2757 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002758 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002759 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302762
2763 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2764 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2765 ALOGE(" sound card is not active rejecting compress output open request");
2766 return -EINVAL;
2767 }
2768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2770
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302771 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2772 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2773 devices, flags, &out->stream);
2774
2775
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002776 if (!out) {
2777 return -ENOMEM;
2778 }
2779
Haynes Mathew George204045b2015-02-25 20:32:03 -08002780 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2781 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 if (devices == AUDIO_DEVICE_NONE)
2784 devices = AUDIO_DEVICE_OUT_SPEAKER;
2785
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 out->flags = flags;
2787 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002788 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002789 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002790 out->sample_rate = config->sample_rate;
2791 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2792 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002793 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002794 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002795 out->non_blocking = 0;
2796 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797
2798 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302799 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2800 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002801 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2802 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2803
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002804 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002805 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2806 ret = read_hdmi_channel_masks(out);
2807
2808 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2809 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002810 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002811 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002812 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002813
2814 if (config->sample_rate == 0)
2815 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2816 if (config->channel_mask == 0)
2817 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2818
2819 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002820 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2822 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002824 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002826 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2827 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002828 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002829 ret = voice_extn_compress_voip_open_output_stream(out);
2830 if (ret != 0) {
2831 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2832 __func__, ret);
2833 goto error_open;
2834 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2836 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2837 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2838 ALOGE("%s: Unsupported Offload information", __func__);
2839 ret = -EINVAL;
2840 goto error_open;
2841 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002842
2843 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2844 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2845 ALOGV("read and update_pass through formats");
2846 ret = audio_extn_dolby_update_passt_formats(adev, out);
2847 if(ret != 0) {
2848 goto error_open;
2849 }
2850 if(config->offload_info.format == 0)
2851 config->offload_info.format = out->supported_formats[0];
2852 }
2853
Mingming Yin90310102013-11-13 16:57:00 -08002854 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002855 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 ALOGE("%s: Unsupported audio format", __func__);
2857 ret = -EINVAL;
2858 goto error_open;
2859 }
2860
2861 out->compr_config.codec = (struct snd_codec *)
2862 calloc(1, sizeof(struct snd_codec));
2863
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002864 if (!out->compr_config.codec) {
2865 ret = -ENOMEM;
2866 goto error_open;
2867 }
2868
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002869 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 if (config->offload_info.channel_mask)
2871 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002872 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002874 config->offload_info.channel_mask = config->channel_mask;
2875 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002876 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 out->sample_rate = config->offload_info.sample_rate;
2878
2879 out->stream.set_callback = out_set_callback;
2880 out->stream.pause = out_pause;
2881 out->stream.resume = out_resume;
2882 out->stream.drain = out_drain;
2883 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002884 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002886 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002887 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002888 audio_extn_dolby_get_snd_codec_id(adev, out,
2889 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002890 else
2891 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002893 if (audio_is_offload_pcm(config->offload_info.format)) {
2894 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002895 platform_get_pcm_offload_buffer_size(&config->offload_info);
2896 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2897 out->compr_config.fragment_size =
2898 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002899 } else {
2900 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002901 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002902 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2904 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302905 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 out->compr_config.codec->bit_rate =
2907 config->offload_info.bit_rate;
2908 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002909 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002911 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002912 /*TODO: Do we need to change it for passthrough */
2913 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914
Mingming Yin3ee55c62014-08-04 14:23:35 -07002915 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2916 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002917 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2918 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002919 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002920 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2921
Mingming Yin3ee55c62014-08-04 14:23:35 -07002922 if (out->bit_width == 24) {
2923 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2924 }
2925
Amit Shekhar6f461b12014-08-01 14:52:58 -07002926 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002927 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2930 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002931
Sharad Sangleb27354b2015-06-18 15:58:55 +05302932 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002933 //this flag is set from framework only if its for PCM formats
2934 //no need to check for PCM format again
2935 out->non_blocking = 0;
2936 out->use_small_bufs = true;
2937 ALOGI("Keep write blocking for small buff: non_blockling %d",
2938 out->non_blocking);
2939 }
2940
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002941 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002942 out->offload_state = OFFLOAD_STATE_IDLE;
2943 out->playback_started = 0;
2944
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002945 audio_extn_dts_create_state_notifier_node(out->usecase);
2946
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002947 create_offload_callback_thread(out);
2948 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2949 __func__, config->offload_info.version,
2950 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002951 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002952 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002953 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2954 ret = voice_check_and_set_incall_music_usecase(adev, out);
2955 if (ret != 0) {
2956 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2957 __func__, ret);
2958 goto error_open;
2959 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002960 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2961 if (config->sample_rate == 0)
2962 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2963 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2964 config->sample_rate != 8000) {
2965 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2966 ret = -EINVAL;
2967 goto error_open;
2968 }
2969 out->sample_rate = config->sample_rate;
2970 out->config.rate = config->sample_rate;
2971 if (config->format == AUDIO_FORMAT_DEFAULT)
2972 config->format = AUDIO_FORMAT_PCM_16_BIT;
2973 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2974 config->format = AUDIO_FORMAT_PCM_16_BIT;
2975 ret = -EINVAL;
2976 goto error_open;
2977 }
2978 out->format = config->format;
2979 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2980 out->config = pcm_config_afe_proxy_playback;
2981 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002982 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002983 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2985 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002986 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002987 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2988 format = AUDIO_FORMAT_PCM_16_BIT;
2989 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2990 out->config = pcm_config_deep_buffer;
2991 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002992 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002993 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002994 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002995 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002996 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002997 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 }
2999
Amit Shekhar1d896042014-10-03 13:16:09 -07003000 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3001 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003002 /* TODO remove this hardcoding and check why width is zero*/
3003 if (out->bit_width == 0)
3004 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003005 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3006 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003007 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303008 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003009 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3010 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3011 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003012 if(adev->primary_output == NULL)
3013 adev->primary_output = out;
3014 else {
3015 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003016 ret = -EEXIST;
3017 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003018 }
3019 }
3020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 /* Check if this usecase is already existing */
3022 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003023 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3024 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003027 ret = -EEXIST;
3028 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 }
3030 pthread_mutex_unlock(&adev->lock);
3031
3032 out->stream.common.get_sample_rate = out_get_sample_rate;
3033 out->stream.common.set_sample_rate = out_set_sample_rate;
3034 out->stream.common.get_buffer_size = out_get_buffer_size;
3035 out->stream.common.get_channels = out_get_channels;
3036 out->stream.common.get_format = out_get_format;
3037 out->stream.common.set_format = out_set_format;
3038 out->stream.common.standby = out_standby;
3039 out->stream.common.dump = out_dump;
3040 out->stream.common.set_parameters = out_set_parameters;
3041 out->stream.common.get_parameters = out_get_parameters;
3042 out->stream.common.add_audio_effect = out_add_audio_effect;
3043 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3044 out->stream.get_latency = out_get_latency;
3045 out->stream.set_volume = out_set_volume;
3046 out->stream.write = out_write;
3047 out->stream.get_render_position = out_get_render_position;
3048 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003049 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003052 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003053 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054
3055 config->format = out->stream.common.get_format(&out->stream.common);
3056 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3057 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3058
3059 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303060 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3061 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003062
3063 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3064 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3065 popcount(out->channel_mask), out->playback_started);
3066
Eric Laurent994a6932013-07-17 11:51:42 -07003067 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003069
3070error_open:
3071 free(out);
3072 *stream_out = NULL;
3073 ALOGD("%s: exit: ret %d", __func__, ret);
3074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075}
3076
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003077static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 struct audio_stream_out *stream)
3079{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 struct stream_out *out = (struct stream_out *)stream;
3081 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003082 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303084 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3085
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003086 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303087 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003088 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303089 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003090 if(ret != 0)
3091 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3092 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003093 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003094 out_standby(&stream->common);
3095
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003096 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003097 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003099 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003100 if (out->compr_config.codec != NULL)
3101 free(out->compr_config.codec);
3102 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003103
3104 if (adev->voice_tx_output == out)
3105 adev->voice_tx_output = NULL;
3106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 pthread_cond_destroy(&out->cond);
3108 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003110 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111}
3112
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003113static void close_compress_sessions(struct audio_device *adev)
3114{
Mingming Yin7b762e72015-03-04 13:47:32 -08003115 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303116 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003117 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003118 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303119
3120 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003121 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303122 if (is_offload_usecase(usecase->id)) {
3123 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003124 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3125 out = usecase->stream.out;
3126 pthread_mutex_unlock(&adev->lock);
3127 out_standby(&out->stream.common);
3128 pthread_mutex_lock(&adev->lock);
3129 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303130 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003131 }
3132 pthread_mutex_unlock(&adev->lock);
3133}
3134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3136{
3137 struct audio_device *adev = (struct audio_device *)dev;
3138 struct str_parms *parms;
3139 char *str;
3140 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003141 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003142 int ret;
3143 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003145 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303148 if (!parms)
3149 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003150 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3151 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303152 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303153 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303154 struct listnode *node;
3155 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303156 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303157 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003158 //close compress sessions on OFFLINE status
3159 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303160 } else if (strstr(snd_card_status, "ONLINE")) {
3161 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303162 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303163 if (!platform_is_acdb_initialized(adev->platform)) {
3164 ret = platform_acdb_init(adev->platform);
3165 if(ret)
3166 ALOGE("acdb initialization is failed");
3167
3168 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303169 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303170 }
3171
3172 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003173 status = voice_set_parameters(adev, parms);
3174 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003175 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003177 status = platform_set_parameters(adev->platform, parms);
3178 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003179 goto done;
3180
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003181 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3182 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003183 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3185 adev->bluetooth_nrec = true;
3186 else
3187 adev->bluetooth_nrec = false;
3188 }
3189
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003190 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3191 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3193 adev->screen_off = false;
3194 else
3195 adev->screen_off = true;
3196 }
3197
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003198 ret = str_parms_get_int(parms, "rotation", &val);
3199 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003200 bool reverse_speakers = false;
3201 switch(val) {
3202 // FIXME: note that the code below assumes that the speakers are in the correct placement
3203 // relative to the user when the device is rotated 90deg from its default rotation. This
3204 // assumption is device-specific, not platform-specific like this code.
3205 case 270:
3206 reverse_speakers = true;
3207 break;
3208 case 0:
3209 case 90:
3210 case 180:
3211 break;
3212 default:
3213 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003214 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003215 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003216 if (status == 0) {
3217 if (adev->speaker_lr_swap != reverse_speakers) {
3218 adev->speaker_lr_swap = reverse_speakers;
3219 // only update the selected device if there is active pcm playback
3220 struct audio_usecase *usecase;
3221 struct listnode *node;
3222 list_for_each(node, &adev->usecase_list) {
3223 usecase = node_to_item(node, struct audio_usecase, list);
3224 if (usecase->type == PCM_PLAYBACK) {
3225 select_devices(adev, usecase->id);
3226 break;
3227 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003228 }
3229 }
3230 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003231 }
3232
Mingming Yin514a8bc2014-07-29 15:22:21 -07003233 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3234 if (ret >= 0) {
3235 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3236 adev->bt_wb_speech_enabled = true;
3237 else
3238 adev->bt_wb_speech_enabled = false;
3239 }
3240
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3242 if (ret >= 0) {
3243 val = atoi(value);
3244 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3245 ALOGV("cache new edid");
3246 platform_cache_edid(adev->platform);
3247 }
3248 }
3249
3250 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3251 if (ret >= 0) {
3252 val = atoi(value);
3253 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3254 ALOGV("invalidate cached edid");
3255 platform_invalidate_edid(adev->platform);
3256 }
3257 }
3258
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003259 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003260
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003261done:
3262 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003263 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303264error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003265 ALOGV("%s: exit with code(%d)", __func__, status);
3266 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267}
3268
3269static char* adev_get_parameters(const struct audio_hw_device *dev,
3270 const char *keys)
3271{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003272 struct audio_device *adev = (struct audio_device *)dev;
3273 struct str_parms *reply = str_parms_create();
3274 struct str_parms *query = str_parms_create_str(keys);
3275 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303276 char value[256] = {0};
3277 int ret = 0;
3278
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003279 if (!query || !reply) {
3280 ALOGE("adev_get_parameters: failed to create query or reply");
3281 return NULL;
3282 }
3283
Naresh Tannirud7205b62014-06-20 02:54:48 +05303284 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3285 sizeof(value));
3286 if (ret >=0) {
3287 int val = 1;
3288 pthread_mutex_lock(&adev->snd_card_status.lock);
3289 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3290 val = 0;
3291 pthread_mutex_unlock(&adev->snd_card_status.lock);
3292 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3293 goto exit;
3294 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003295
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003296 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003297 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003298 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003299 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303300 pthread_mutex_unlock(&adev->lock);
3301
Naresh Tannirud7205b62014-06-20 02:54:48 +05303302exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003303 str = str_parms_to_str(reply);
3304 str_parms_destroy(query);
3305 str_parms_destroy(reply);
3306
3307 ALOGV("%s: exit: returns - %s", __func__, str);
3308 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309}
3310
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003311static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312{
3313 return 0;
3314}
3315
3316static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3317{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003318 int ret;
3319 struct audio_device *adev = (struct audio_device *)dev;
3320 pthread_mutex_lock(&adev->lock);
3321 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003322 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003323 pthread_mutex_unlock(&adev->lock);
3324 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325}
3326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003327static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3328 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329{
3330 return -ENOSYS;
3331}
3332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003333static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3334 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335{
3336 return -ENOSYS;
3337}
3338
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003339static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3340 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341{
3342 return -ENOSYS;
3343}
3344
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003345static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3346 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 return -ENOSYS;
3349}
3350
3351static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3352{
3353 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 pthread_mutex_lock(&adev->lock);
3356 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003357 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003359 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3360 voice_is_in_call(adev)) {
3361 voice_stop_call(adev);
3362 adev->current_call_output = NULL;
3363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 }
3365 pthread_mutex_unlock(&adev->lock);
3366 return 0;
3367}
3368
3369static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3370{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003371 int ret;
3372
3373 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003374 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003375 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3376 pthread_mutex_unlock(&adev->lock);
3377
3378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379}
3380
3381static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3382{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003383 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 return 0;
3385}
3386
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003387static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 const struct audio_config *config)
3389{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003390 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003392 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3393 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394}
3395
3396static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003397 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 audio_devices_t devices,
3399 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003400 struct audio_stream_in **stream_in,
3401 audio_input_flags_t flags __unused,
3402 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003403 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404{
3405 struct audio_device *adev = (struct audio_device *)dev;
3406 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003407 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003408 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003409 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 *stream_in = NULL;
3412 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3413 return -EINVAL;
3414
3415 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003416
3417 if (!in) {
3418 ALOGE("failed to allocate input stream");
3419 return -ENOMEM;
3420 }
3421
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303422 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003423 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3424 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003426 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 in->stream.common.get_sample_rate = in_get_sample_rate;
3429 in->stream.common.set_sample_rate = in_set_sample_rate;
3430 in->stream.common.get_buffer_size = in_get_buffer_size;
3431 in->stream.common.get_channels = in_get_channels;
3432 in->stream.common.get_format = in_get_format;
3433 in->stream.common.set_format = in_set_format;
3434 in->stream.common.standby = in_standby;
3435 in->stream.common.dump = in_dump;
3436 in->stream.common.set_parameters = in_set_parameters;
3437 in->stream.common.get_parameters = in_get_parameters;
3438 in->stream.common.add_audio_effect = in_add_audio_effect;
3439 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3440 in->stream.set_gain = in_set_gain;
3441 in->stream.read = in_read;
3442 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3443
3444 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003445 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 in->standby = 1;
3448 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003449 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450
3451 /* Update config params with the requested sample rate and channels */
3452 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003453 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3454 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3455 is_low_latency = true;
3456#if LOW_LATENCY_CAPTURE_USE_CASE
3457 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3458#endif
3459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003462 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003464 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303465 if (adev->mode != AUDIO_MODE_IN_CALL) {
3466 ret = -EINVAL;
3467 goto err_open;
3468 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003469 if (config->sample_rate == 0)
3470 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3471 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3472 config->sample_rate != 8000) {
3473 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477 if (config->format == AUDIO_FORMAT_DEFAULT)
3478 config->format = AUDIO_FORMAT_PCM_16_BIT;
3479 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3480 config->format = AUDIO_FORMAT_PCM_16_BIT;
3481 ret = -EINVAL;
3482 goto err_open;
3483 }
3484
3485 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3486 in->config = pcm_config_afe_proxy_record;
3487 in->config.channels = channel_count;
3488 in->config.rate = config->sample_rate;
3489 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003490 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003491 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003492 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3493 ret = -EINVAL;
3494 goto err_open;
3495 }
3496 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003497 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003498 }
Mingming Yine62d7842013-10-25 16:26:03 -07003499 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003500 audio_extn_compr_cap_format_supported(config->format) &&
3501 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003502 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003503 } else {
3504 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003505 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003506 buffer_size = get_input_buffer_size(config->sample_rate,
3507 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003508 channel_count,
3509 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003510 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003511 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3512 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3513 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3514 (in->config.rate == 8000 || in->config.rate == 16000) &&
3515 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3516 voice_extn_compress_voip_open_input_stream(in);
3517 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003518 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003520 /* This stream could be for sound trigger lab,
3521 get sound trigger pcm if present */
3522 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303523 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003526 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003527 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
3529err_open:
3530 free(in);
3531 *stream_in = NULL;
3532 return ret;
3533}
3534
3535static void adev_close_input_stream(struct audio_hw_device *dev,
3536 struct audio_stream_in *stream)
3537{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003538 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003539 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003540 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303541
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303542 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003543
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303544 /* Disable echo reference while closing input stream */
3545 platform_set_echo_reference(adev->platform, false);
3546
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003547 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303548 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303550 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003551 if (ret != 0)
3552 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3553 __func__, ret);
3554 } else
3555 in_standby(&stream->common);
3556
Mingming Yin7b762e72015-03-04 13:47:32 -08003557 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003558 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003559 audio_extn_ssr_deinit();
3560 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561
Mingming Yine62d7842013-10-25 16:26:03 -07003562 if(audio_extn_compr_cap_enabled() &&
3563 audio_extn_compr_cap_format_supported(in->config.format))
3564 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003565
3566 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 return;
3568}
3569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003570static int adev_dump(const audio_hw_device_t *device __unused,
3571 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572{
3573 return 0;
3574}
3575
3576static int adev_close(hw_device_t *device)
3577{
3578 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003579
3580 if (!adev)
3581 return 0;
3582
3583 pthread_mutex_lock(&adev_init_lock);
3584
3585 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003586 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003587 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003588 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003589 audio_route_free(adev->audio_route);
3590 free(adev->snd_dev_ref_cnt);
3591 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003592 free(device);
3593 adev = NULL;
3594 }
3595 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 return 0;
3597}
3598
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003599/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3600 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3601 * just that it _might_ work.
3602 */
3603static int period_size_is_plausible_for_low_latency(int period_size)
3604{
3605 switch (period_size) {
3606 case 160:
3607 case 240:
3608 case 320:
3609 case 480:
3610 return 1;
3611 default:
3612 return 0;
3613 }
3614}
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616static int adev_open(const hw_module_t *module, const char *name,
3617 hw_device_t **device)
3618{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003619 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003621 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3623
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003624 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003625 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003626 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003627 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003628 ALOGD("%s: returning existing instance of adev", __func__);
3629 ALOGD("%s: exit", __func__);
3630 pthread_mutex_unlock(&adev_init_lock);
3631 return 0;
3632 }
3633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634 adev = calloc(1, sizeof(struct audio_device));
3635
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003636 if (!adev) {
3637 pthread_mutex_unlock(&adev_init_lock);
3638 return -ENOMEM;
3639 }
3640
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003641 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003643 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3644 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3645 adev->device.common.module = (struct hw_module_t *)module;
3646 adev->device.common.close = adev_close;
3647
3648 adev->device.init_check = adev_init_check;
3649 adev->device.set_voice_volume = adev_set_voice_volume;
3650 adev->device.set_master_volume = adev_set_master_volume;
3651 adev->device.get_master_volume = adev_get_master_volume;
3652 adev->device.set_master_mute = adev_set_master_mute;
3653 adev->device.get_master_mute = adev_get_master_mute;
3654 adev->device.set_mode = adev_set_mode;
3655 adev->device.set_mic_mute = adev_set_mic_mute;
3656 adev->device.get_mic_mute = adev_get_mic_mute;
3657 adev->device.set_parameters = adev_set_parameters;
3658 adev->device.get_parameters = adev_get_parameters;
3659 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3660 adev->device.open_output_stream = adev_open_output_stream;
3661 adev->device.close_output_stream = adev_close_output_stream;
3662 adev->device.open_input_stream = adev_open_input_stream;
3663 adev->device.close_input_stream = adev_close_input_stream;
3664 adev->device.dump = adev_dump;
3665
3666 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003668 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003669 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003672 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003673 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003674 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003675 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003676 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003677 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003678 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303679
3680 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3681 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003683 adev->platform = platform_init(adev);
3684 if (!adev->platform) {
3685 free(adev->snd_dev_ref_cnt);
3686 free(adev);
3687 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3688 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003689 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003690 return -EINVAL;
3691 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003692
Naresh Tanniru4c630392014-05-12 01:05:52 +05303693 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3694
Eric Laurentc4aef752013-09-12 17:45:53 -07003695 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3696 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3697 if (adev->visualizer_lib == NULL) {
3698 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3699 } else {
3700 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3701 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003702 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003703 "visualizer_hal_start_output");
3704 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003705 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003706 "visualizer_hal_stop_output");
3707 }
3708 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003709 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003710 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003711
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003712 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3713 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3714 if (adev->offload_effects_lib == NULL) {
3715 ALOGE("%s: DLOPEN failed for %s", __func__,
3716 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3717 } else {
3718 ALOGV("%s: DLOPEN successful for %s", __func__,
3719 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3720 adev->offload_effects_start_output =
3721 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3722 "offload_effects_bundle_hal_start_output");
3723 adev->offload_effects_stop_output =
3724 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3725 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003726 adev->offload_effects_set_hpx_state =
3727 (int (*)(bool))dlsym(adev->offload_effects_lib,
3728 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 }
3730 }
3731
Mingming Yin514a8bc2014-07-29 15:22:21 -07003732 adev->bt_wb_speech_enabled = false;
3733
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003734 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 *device = &adev->device.common;
3736
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003737 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3738 &adev->streams_output_cfg_list);
3739
Kiran Kandi910e1862013-10-29 13:29:42 -07003740 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003741
3742 char value[PROPERTY_VALUE_MAX];
3743 int trial;
3744 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3745 trial = atoi(value);
3746 if (period_size_is_plausible_for_low_latency(trial)) {
3747 pcm_config_low_latency.period_size = trial;
3748 pcm_config_low_latency.start_threshold = trial / 4;
3749 pcm_config_low_latency.avail_min = trial / 4;
3750 configured_low_latency_capture_period_size = trial;
3751 }
3752 }
3753 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3754 trial = atoi(value);
3755 if (period_size_is_plausible_for_low_latency(trial)) {
3756 configured_low_latency_capture_period_size = trial;
3757 }
3758 }
3759
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003760 pthread_mutex_unlock(&adev_init_lock);
3761
Eric Laurent994a6932013-07-17 11:51:42 -07003762 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 return 0;
3764}
3765
3766static struct hw_module_methods_t hal_module_methods = {
3767 .open = adev_open,
3768};
3769
3770struct audio_module HAL_MODULE_INFO_SYM = {
3771 .common = {
3772 .tag = HARDWARE_MODULE_TAG,
3773 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3774 .hal_api_version = HARDWARE_HAL_API_VERSION,
3775 .id = AUDIO_HARDWARE_MODULE_ID,
3776 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003777 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 .methods = &hal_module_methods,
3779 },
3780};