blob: 3286e6b8bf0631a976a91ba52c19b899cfc45bc9 [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) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530629 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530630 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700631 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700632 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700633 switch_device[usecase->id] = true;
634 num_uc_to_switch++;
635 }
636 }
637
638 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700639 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530641 /* Make sure the previous devices to be disabled first and then enable the
642 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643 list_for_each(node, &adev->usecase_list) {
644 usecase = node_to_item(node, struct audio_usecase, list);
645 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700646 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700647 }
648 }
649
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700650 list_for_each(node, &adev->usecase_list) {
651 usecase = node_to_item(node, struct audio_usecase, list);
652 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700653 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700654 }
655 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657 /* Re-route all the usecases on the shared backend other than the
658 specified usecase to new snd devices */
659 list_for_each(node, &adev->usecase_list) {
660 usecase = node_to_item(node, struct audio_usecase, list);
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 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700874 select_devices(adev, adev->active_input->usecase);
875 }
876 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 } else if (usecase->type == PCM_CAPTURE) {
878 usecase->devices = usecase->stream.in->device;
879 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700881 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530882 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
883 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
884 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
885 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700886 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800887 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700888 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
889 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700890 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 }
895
896 if (out_snd_device == usecase->out_snd_device &&
897 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800898 return 0;
899 }
900
sangwoobc677242013-08-08 16:53:43 +0900901 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700902 out_snd_device, platform_get_snd_device_name(out_snd_device),
903 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 /*
906 * Limitation: While in call, to do a device switch we need to disable
907 * and enable both RX and TX devices though one of them is same as current
908 * device.
909 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700910 if ((usecase->type == VOICE_CALL) &&
911 (usecase->in_snd_device != SND_DEVICE_NONE) &&
912 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700913 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700914 /* Disable sidetone only if voice call already exists */
915 if (voice_is_call_state_active(adev))
916 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800917 }
918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 /* Disable current sound devices */
920 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700921 disable_audio_route(adev, usecase);
922 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800923 }
924
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700926 disable_audio_route(adev, usecase);
927 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 }
929
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800930 /* Applicable only on the targets that has external modem.
931 * New device information should be sent to modem before enabling
932 * the devices to reduce in-call device switch time.
933 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700934 if ((usecase->type == VOICE_CALL) &&
935 (usecase->in_snd_device != SND_DEVICE_NONE) &&
936 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800937 status = platform_switch_voice_call_enable_device_config(adev->platform,
938 out_snd_device,
939 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700940 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800941
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 /* Enable new sound devices */
943 if (out_snd_device != SND_DEVICE_NONE) {
944 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
945 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700946 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947 }
948
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 if (in_snd_device != SND_DEVICE_NONE) {
950 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700951 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700953
Avinash Vaish71a8b972014-07-24 15:36:33 +0530954 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700955 status = platform_switch_voice_call_device_post(adev->platform,
956 out_snd_device,
957 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530958 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700959 /* Enable sidetone only if voice call already exists */
960 if (voice_is_call_state_active(adev))
961 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530962 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800963
sangwoo170731f2013-06-08 15:36:36 +0900964 usecase->in_snd_device = in_snd_device;
965 usecase->out_snd_device = out_snd_device;
966
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530967 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700968 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530969 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700970 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530971 usecase->stream.out->flags,
972 usecase->stream.out->format,
973 usecase->stream.out->sample_rate,
974 usecase->stream.out->bit_width,
975 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700976 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530977 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700978
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700979 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900980
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800981 /* Applicable only on the targets that has external modem.
982 * Enable device command should be sent to modem only after
983 * enabling voice call mixer controls
984 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700985 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800986 status = platform_switch_voice_call_usecase_route_post(adev->platform,
987 out_snd_device,
988 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530989 ALOGD("%s: done",__func__);
990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 return status;
992}
993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994static int stop_input_stream(struct stream_in *in)
995{
996 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 struct audio_usecase *uc_info;
998 struct audio_device *adev = in->dev;
999
Eric Laurentc8400632013-02-14 19:04:54 -08001000 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001
Eric Laurent994a6932013-07-17 11:51:42 -07001002 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004 uc_info = get_usecase_from_list(adev, in->usecase);
1005 if (uc_info == NULL) {
1006 ALOGE("%s: Could not find the usecase (%d) in the list",
1007 __func__, in->usecase);
1008 return -EINVAL;
1009 }
1010
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001011 /* Close in-call recording streams */
1012 voice_check_and_stop_incall_rec_usecase(adev, in);
1013
Eric Laurent150dbfe2013-02-27 14:31:02 -08001014 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001015 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016
1017 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001018 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001020 list_remove(&uc_info->list);
1021 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Eric Laurent994a6932013-07-17 11:51:42 -07001023 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 return ret;
1025}
1026
1027int start_input_stream(struct stream_in *in)
1028{
1029 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001030 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 struct audio_usecase *uc_info;
1032 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301033 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301035 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1036 if (get_usecase_from_list(adev, usecase) == NULL)
1037 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301038 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1039 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001040
Naresh Tanniru80659832014-06-04 18:17:56 +05301041
1042 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301043 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301044 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301045 goto error_config;
1046 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301047
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001048 /* Check if source matches incall recording usecase criteria */
1049 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1050 if (ret)
1051 goto error_config;
1052 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301053 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1054
1055 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1056 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1057 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1058 goto error_config;
1059 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001060
Eric Laurentb23d5282013-05-14 15:27:20 -07001061 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 if (in->pcm_device_id < 0) {
1063 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1064 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001065 ret = -EINVAL;
1066 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001068
1069 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001071
1072 if (!uc_info) {
1073 ret = -ENOMEM;
1074 goto error_config;
1075 }
1076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001077 uc_info->id = in->usecase;
1078 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001079 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001080 uc_info->devices = in->device;
1081 uc_info->in_snd_device = SND_DEVICE_NONE;
1082 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001084 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301085 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087
Eric Laurentc8400632013-02-14 19:04:54 -08001088 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001089 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1090
1091 unsigned int flags = PCM_IN;
1092 unsigned int pcm_open_retry_count = 0;
1093
1094 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1095 flags |= PCM_MMAP | PCM_NOIRQ;
1096 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1097 }
1098
1099 while (1) {
1100 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1101 flags, &in->config);
1102 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1103 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1104 if (in->pcm != NULL) {
1105 pcm_close(in->pcm);
1106 in->pcm = NULL;
1107 }
1108 if (pcm_open_retry_count-- == 0) {
1109 ret = -EIO;
1110 goto error_open;
1111 }
1112 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1113 continue;
1114 }
1115 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001116 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301117 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301118
Eric Laurent994a6932013-07-17 11:51:42 -07001119 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001120 return ret;
1121
1122error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301124 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001125
1126error_config:
1127 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001129
1130 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131}
1132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001133/* must be called with out->lock locked */
1134static int send_offload_cmd_l(struct stream_out* out, int command)
1135{
1136 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1137
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001138 if (!cmd) {
1139 ALOGE("failed to allocate mem for command 0x%x", command);
1140 return -ENOMEM;
1141 }
1142
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001143 ALOGVV("%s %d", __func__, command);
1144
1145 cmd->cmd = command;
1146 list_add_tail(&out->offload_cmd_list, &cmd->node);
1147 pthread_cond_signal(&out->offload_cond);
1148 return 0;
1149}
1150
1151/* must be called iwth out->lock locked */
1152static void stop_compressed_output_l(struct stream_out *out)
1153{
1154 out->offload_state = OFFLOAD_STATE_IDLE;
1155 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001156 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001157 if (out->compr != NULL) {
1158 compress_stop(out->compr);
1159 while (out->offload_thread_blocked) {
1160 pthread_cond_wait(&out->cond, &out->lock);
1161 }
1162 }
1163}
1164
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001165bool is_offload_usecase(audio_usecase_t uc_id)
1166{
1167 unsigned int i;
1168 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1169 if (uc_id == offload_usecases[i])
1170 return true;
1171 }
1172 return false;
1173}
1174
1175static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1176{
1177 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1178 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1179 char value[PROPERTY_VALUE_MAX] = {0};
1180
1181 property_get("audio.offload.multiple.enabled", value, NULL);
1182 if (!(atoi(value) || !strncmp("true", value, 4)))
1183 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1184
1185 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1186 for (i = 0; i < num_usecase; i++) {
1187 if (!(adev->offload_usecases_state & (0x1<<i))) {
1188 adev->offload_usecases_state |= 0x1 << i;
1189 ret = offload_usecases[i];
1190 break;
1191 }
1192 }
1193 ALOGV("%s: offload usecase is %d", __func__, ret);
1194 return ret;
1195}
1196
1197static void free_offload_usecase(struct audio_device *adev,
1198 audio_usecase_t uc_id)
1199{
1200 unsigned int i;
1201 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1202 if (offload_usecases[i] == uc_id) {
1203 adev->offload_usecases_state &= ~(0x1<<i);
1204 break;
1205 }
1206 }
1207 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1208}
1209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001210static void *offload_thread_loop(void *context)
1211{
1212 struct stream_out *out = (struct stream_out *) context;
1213 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001214 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001216 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1217 set_sched_policy(0, SP_FOREGROUND);
1218 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1219
1220 ALOGV("%s", __func__);
1221 pthread_mutex_lock(&out->lock);
1222 for (;;) {
1223 struct offload_cmd *cmd = NULL;
1224 stream_callback_event_t event;
1225 bool send_callback = false;
1226
1227 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1228 __func__, list_empty(&out->offload_cmd_list),
1229 out->offload_state);
1230 if (list_empty(&out->offload_cmd_list)) {
1231 ALOGV("%s SLEEPING", __func__);
1232 pthread_cond_wait(&out->offload_cond, &out->lock);
1233 ALOGV("%s RUNNING", __func__);
1234 continue;
1235 }
1236
1237 item = list_head(&out->offload_cmd_list);
1238 cmd = node_to_item(item, struct offload_cmd, node);
1239 list_remove(item);
1240
1241 ALOGVV("%s STATE %d CMD %d out->compr %p",
1242 __func__, out->offload_state, cmd->cmd, out->compr);
1243
1244 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1245 free(cmd);
1246 break;
1247 }
1248
1249 if (out->compr == NULL) {
1250 ALOGE("%s: Compress handle is NULL", __func__);
1251 pthread_cond_signal(&out->cond);
1252 continue;
1253 }
1254 out->offload_thread_blocked = true;
1255 pthread_mutex_unlock(&out->lock);
1256 send_callback = false;
1257 switch(cmd->cmd) {
1258 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001259 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001260 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001261 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001262 send_callback = true;
1263 event = STREAM_CBK_EVENT_WRITE_READY;
1264 break;
1265 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001266 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301267 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001268 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301269 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001270 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301271 if (ret < 0)
1272 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301273 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301274 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001275 compress_drain(out->compr);
1276 else
1277 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301278 if (ret != -ENETRESET) {
1279 send_callback = true;
1280 event = STREAM_CBK_EVENT_DRAIN_READY;
1281 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1282 } else
1283 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001284 break;
1285 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001286 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001287 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001288 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 send_callback = true;
1290 event = STREAM_CBK_EVENT_DRAIN_READY;
1291 break;
1292 default:
1293 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1294 break;
1295 }
1296 pthread_mutex_lock(&out->lock);
1297 out->offload_thread_blocked = false;
1298 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001299 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001300 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001302 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001303 free(cmd);
1304 }
1305
1306 pthread_cond_signal(&out->cond);
1307 while (!list_empty(&out->offload_cmd_list)) {
1308 item = list_head(&out->offload_cmd_list);
1309 list_remove(item);
1310 free(node_to_item(item, struct offload_cmd, node));
1311 }
1312 pthread_mutex_unlock(&out->lock);
1313
1314 return NULL;
1315}
1316
1317static int create_offload_callback_thread(struct stream_out *out)
1318{
1319 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1320 list_init(&out->offload_cmd_list);
1321 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1322 offload_thread_loop, out);
1323 return 0;
1324}
1325
1326static int destroy_offload_callback_thread(struct stream_out *out)
1327{
1328 pthread_mutex_lock(&out->lock);
1329 stop_compressed_output_l(out);
1330 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1331
1332 pthread_mutex_unlock(&out->lock);
1333 pthread_join(out->offload_thread, (void **) NULL);
1334 pthread_cond_destroy(&out->offload_cond);
1335
1336 return 0;
1337}
1338
Eric Laurent07eeafd2013-10-06 12:52:49 -07001339static bool allow_hdmi_channel_config(struct audio_device *adev)
1340{
1341 struct listnode *node;
1342 struct audio_usecase *usecase;
1343 bool ret = true;
1344
1345 list_for_each(node, &adev->usecase_list) {
1346 usecase = node_to_item(node, struct audio_usecase, list);
1347 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1348 /*
1349 * If voice call is already existing, do not proceed further to avoid
1350 * disabling/enabling both RX and TX devices, CSD calls, etc.
1351 * Once the voice call done, the HDMI channels can be configured to
1352 * max channels of remaining use cases.
1353 */
1354 if (usecase->id == USECASE_VOICE_CALL) {
1355 ALOGD("%s: voice call is active, no change in HDMI channels",
1356 __func__);
1357 ret = false;
1358 break;
1359 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1360 ALOGD("%s: multi channel playback is active, "
1361 "no change in HDMI channels", __func__);
1362 ret = false;
1363 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001364 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001365 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001366 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1367 ", no change in HDMI channels", __func__,
1368 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001369 ret = false;
1370 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001371 }
1372 }
1373 }
1374 return ret;
1375}
1376
1377static int check_and_set_hdmi_channels(struct audio_device *adev,
1378 unsigned int channels)
1379{
1380 struct listnode *node;
1381 struct audio_usecase *usecase;
1382
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001383 unsigned int supported_channels = platform_edid_get_max_channels(
1384 adev->platform);
1385 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001386 /* Check if change in HDMI channel config is allowed */
1387 if (!allow_hdmi_channel_config(adev))
1388 return 0;
1389
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001390 if (channels > supported_channels)
1391 channels = supported_channels;
1392
Eric Laurent07eeafd2013-10-06 12:52:49 -07001393 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001394 ALOGD("%s: Requested channels are same as current channels(%d)",
1395 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001396 return 0;
1397 }
1398
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001399 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001400 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001401 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 adev->cur_hdmi_channels = channels;
1403
1404 /*
1405 * Deroute all the playback streams routed to HDMI so that
1406 * the back end is deactivated. Note that backend will not
1407 * be deactivated if any one stream is connected to it.
1408 */
1409 list_for_each(node, &adev->usecase_list) {
1410 usecase = node_to_item(node, struct audio_usecase, list);
1411 if (usecase->type == PCM_PLAYBACK &&
1412 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001413 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001414 }
1415 }
1416
1417 /*
1418 * Enable all the streams disabled above. Now the HDMI backend
1419 * will be activated with new channel configuration
1420 */
1421 list_for_each(node, &adev->usecase_list) {
1422 usecase = node_to_item(node, struct audio_usecase, list);
1423 if (usecase->type == PCM_PLAYBACK &&
1424 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001425 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001426 }
1427 }
1428
1429 return 0;
1430}
1431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432static int stop_output_stream(struct stream_out *out)
1433{
1434 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435 struct audio_usecase *uc_info;
1436 struct audio_device *adev = out->dev;
1437
Eric Laurent994a6932013-07-17 11:51:42 -07001438 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 uc_info = get_usecase_from_list(adev, out->usecase);
1441 if (uc_info == NULL) {
1442 ALOGE("%s: Could not find the usecase (%d) in the list",
1443 __func__, out->usecase);
1444 return -EINVAL;
1445 }
1446
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001447 if (is_offload_usecase(out->usecase) &&
1448 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001449 if (adev->visualizer_stop_output != NULL)
1450 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001451
1452 audio_extn_dts_remove_state_notifier_node(out->usecase);
1453
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001454 if (adev->offload_effects_stop_output != NULL)
1455 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1456 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001457
Eric Laurent150dbfe2013-02-27 14:31:02 -08001458 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001459 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001460
1461 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001464 list_remove(&uc_info->list);
1465 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001467 if (is_offload_usecase(out->usecase) &&
1468 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1469 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1470 ALOGV("Disable passthrough , reset mixer to pcm");
1471 /* NO_PASSTHROUGH */
1472 out->compr_config.codec->compr_passthr = 0;
1473 audio_extn_dolby_set_hdmi_config(adev, out);
1474 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1475 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001476 /* Must be called after removing the usecase from list */
1477 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1478 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1479
Eric Laurent994a6932013-07-17 11:51:42 -07001480 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 return ret;
1482}
1483
1484int start_output_stream(struct stream_out *out)
1485{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001487 int sink_channels = 0;
1488 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 struct audio_usecase *uc_info;
1490 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301491 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001493 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1494 ret = -EINVAL;
1495 goto error_config;
1496 }
1497
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301498 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1499 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1500 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301501
Naresh Tanniru80659832014-06-04 18:17:56 +05301502 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301503 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301504 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301505 goto error_config;
1506 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301507
Eric Laurentb23d5282013-05-14 15:27:20 -07001508 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 if (out->pcm_device_id < 0) {
1510 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1511 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001512 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001513 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 }
1515
1516 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001517
1518 if (!uc_info) {
1519 ret = -ENOMEM;
1520 goto error_config;
1521 }
1522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 uc_info->id = out->usecase;
1524 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001525 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526 uc_info->devices = out->devices;
1527 uc_info->in_snd_device = SND_DEVICE_NONE;
1528 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001529 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001530 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001531 if (is_offload_usecase(out->usecase)) {
1532 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001533 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1534 }
1535 }
Mingming Yin9c041392014-05-01 15:37:31 -07001536 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1537 if (!strncmp("true", prop_value, 4)) {
1538 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001539 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1540 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001541 check_and_set_hdmi_channels(adev, sink_channels);
1542 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001543 if (is_offload_usecase(out->usecase)) {
1544 unsigned int ch_count = out->compr_config.codec->ch_in;
1545 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1546 /* backend channel config for passthrough stream is stereo */
1547 ch_count = 2;
1548 check_and_set_hdmi_channels(adev, ch_count);
1549 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001550 check_and_set_hdmi_channels(adev, out->config.channels);
1551 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001552 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001553 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001554 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 select_devices(adev, out->usecase);
1557
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001558 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1559 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001560 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001561 unsigned int flags = PCM_OUT;
1562 unsigned int pcm_open_retry_count = 0;
1563 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1564 flags |= PCM_MMAP | PCM_NOIRQ;
1565 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1566 } else
1567 flags |= PCM_MONOTONIC;
1568
1569 while (1) {
1570 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1571 flags, &out->config);
1572 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1573 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1574 if (out->pcm != NULL) {
1575 pcm_close(out->pcm);
1576 out->pcm = NULL;
1577 }
1578 if (pcm_open_retry_count-- == 0) {
1579 ret = -EIO;
1580 goto error_open;
1581 }
1582 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1583 continue;
1584 }
1585 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001587 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1588 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001590 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1591 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001593 out->compr = compress_open(adev->snd_card,
1594 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001595 COMPRESS_IN, &out->compr_config);
1596 if (out->compr && !is_compress_ready(out->compr)) {
1597 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1598 compress_close(out->compr);
1599 out->compr = NULL;
1600 ret = -EIO;
1601 goto error_open;
1602 }
1603 if (out->offload_callback)
1604 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001605
Fred Oh3f43e742015-03-04 18:42:34 -08001606 /* Since small bufs uses blocking writes, a write will be blocked
1607 for the default max poll time (20s) in the event of an SSR.
1608 Reduce the poll time to observe and deal with SSR faster.
1609 */
1610 if (out->use_small_bufs) {
1611 compress_set_max_poll_wait(out->compr, 1000);
1612 }
1613
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001614 audio_extn_dts_create_state_notifier_node(out->usecase);
1615 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1616 popcount(out->channel_mask),
1617 out->playback_started);
1618
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001619#ifdef DS1_DOLBY_DDP_ENABLED
1620 if (audio_extn_is_dolby_format(out->format))
1621 audio_extn_dolby_send_ddp_endp_params(adev);
1622#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001623 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1624 if (adev->visualizer_start_output != NULL)
1625 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1626 if (adev->offload_effects_start_output != NULL)
1627 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001628 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630 }
Eric Laurent994a6932013-07-17 11:51:42 -07001631 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001633error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001635error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001636 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637}
1638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639static int check_input_parameters(uint32_t sample_rate,
1640 audio_format_t format,
1641 int channel_count)
1642{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001643 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001645 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001646 !voice_extn_compress_voip_is_format_supported(format) &&
1647 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001648
1649 switch (channel_count) {
1650 case 1:
1651 case 2:
1652 case 6:
1653 break;
1654 default:
1655 ret = -EINVAL;
1656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001657
1658 switch (sample_rate) {
1659 case 8000:
1660 case 11025:
1661 case 12000:
1662 case 16000:
1663 case 22050:
1664 case 24000:
1665 case 32000:
1666 case 44100:
1667 case 48000:
1668 break;
1669 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001670 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 }
1672
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001673 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674}
1675
1676static size_t get_input_buffer_size(uint32_t sample_rate,
1677 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001678 int channel_count,
1679 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680{
1681 size_t size = 0;
1682
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001683 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1684 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001686 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001687 if (is_low_latency)
1688 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001689 /* ToDo: should use frame_size computed based on the format and
1690 channel_count here. */
1691 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001693 /* make sure the size is multiple of 32 bytes
1694 * At 48 kHz mono 16-bit PCM:
1695 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1696 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1697 */
1698 size += 0x1f;
1699 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001700
1701 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702}
1703
1704static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1705{
1706 struct stream_out *out = (struct stream_out *)stream;
1707
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709}
1710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001711static int out_set_sample_rate(struct audio_stream *stream __unused,
1712 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713{
1714 return -ENOSYS;
1715}
1716
1717static size_t out_get_buffer_size(const struct audio_stream *stream)
1718{
1719 struct stream_out *out = (struct stream_out *)stream;
1720
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001721 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001723 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1724 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001726 return out->config.period_size *
1727 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728}
1729
1730static uint32_t out_get_channels(const struct audio_stream *stream)
1731{
1732 struct stream_out *out = (struct stream_out *)stream;
1733
1734 return out->channel_mask;
1735}
1736
1737static audio_format_t out_get_format(const struct audio_stream *stream)
1738{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 struct stream_out *out = (struct stream_out *)stream;
1740
1741 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742}
1743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001744static int out_set_format(struct audio_stream *stream __unused,
1745 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746{
1747 return -ENOSYS;
1748}
1749
1750static int out_standby(struct audio_stream *stream)
1751{
1752 struct stream_out *out = (struct stream_out *)stream;
1753 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301755 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1756 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001757 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1758 /* Ignore standby in case of voip call because the voip output
1759 * stream is closed in adev_close_output_stream()
1760 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301761 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 return 0;
1763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001767 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001769 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 if (out->pcm) {
1771 pcm_close(out->pcm);
1772 out->pcm = NULL;
1773 }
1774 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001775 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001776 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001777 out->gapless_mdata.encoder_delay = 0;
1778 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 if (out->compr != NULL) {
1780 compress_close(out->compr);
1781 out->compr = NULL;
1782 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001783 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001785 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 }
1787 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001788 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 return 0;
1790}
1791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001792static int out_dump(const struct audio_stream *stream __unused,
1793 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794{
1795 return 0;
1796}
1797
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1799{
1800 int ret = 0;
1801 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001802 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001803
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001804 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001805 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001806 return -EINVAL;
1807 }
1808
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001809 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1810 if (ret >= 0) {
1811 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1812 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1813 ALOGV("ADTS format is set in offload mode");
1814 }
1815 out->send_new_metadata = 1;
1816 }
1817
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301818 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001819
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1821 if(ret >= 0)
1822 is_meta_data_params = true;
1823 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301824 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001825 is_meta_data_params = true;
1826 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301827 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001828 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001829 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1830 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001831 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301832 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001833 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1835 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001836 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301837 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838 }
1839
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001840 if(!is_meta_data_params) {
1841 ALOGV("%s: Not gapless meta data params", __func__);
1842 return 0;
1843 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844 out->send_new_metadata = 1;
1845 ALOGV("%s new encoder delay %u and padding %u", __func__,
1846 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1847
1848 return 0;
1849}
1850
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001851static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1852{
1853 return out == adev->primary_output || out == adev->voice_tx_output;
1854}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1857{
1858 struct stream_out *out = (struct stream_out *)stream;
1859 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001860 struct audio_usecase *usecase;
1861 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 struct str_parms *parms;
1863 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001864 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001865 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
sangwoobc677242013-08-08 16:53:43 +09001867 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301870 if (!parms)
1871 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001872 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1873 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001876 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001878 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301879 * When HDMI cable is unplugged/usb hs is disconnected the
1880 * music playback is paused and the policy manager sends routing=0
1881 * But the audioflingercontinues to write data until standby time
1882 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 * Avoid this by routing audio to speaker until standby.
1884 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301885 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1886 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001887 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001888 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1889 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001890 }
1891
1892 /*
1893 * select_devices() call below switches all the usecases on the same
1894 * backend to the new device. Refer to check_usecases_codec_backend() in
1895 * the select_devices(). But how do we undo this?
1896 *
1897 * For example, music playback is active on headset (deep-buffer usecase)
1898 * and if we go to ringtones and select a ringtone, low-latency usecase
1899 * will be started on headset+speaker. As we can't enable headset+speaker
1900 * and headset devices at the same time, select_devices() switches the music
1901 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1902 * So when the ringtone playback is completed, how do we undo the same?
1903 *
1904 * We are relying on the out_set_parameters() call on deep-buffer output,
1905 * once the ringtone playback is ended.
1906 * NOTE: We should not check if the current devices are same as new devices.
1907 * Because select_devices() must be called to switch back the music
1908 * playback to headset.
1909 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001910 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001911 out->devices = val;
1912
1913 if (!out->standby)
1914 select_devices(adev, out->usecase);
1915
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001916 if (output_drives_call(adev, out)) {
1917 if(!voice_is_in_call(adev)) {
1918 if (adev->mode == AUDIO_MODE_IN_CALL) {
1919 adev->current_call_output = out;
1920 ret = voice_start_call(adev);
1921 }
1922 } else {
1923 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001924 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001925 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001926 }
1927 }
1928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001930 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001932
1933 if (out == adev->primary_output) {
1934 pthread_mutex_lock(&adev->lock);
1935 audio_extn_set_parameters(adev, parms);
1936 pthread_mutex_unlock(&adev->lock);
1937 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001938 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001939 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001940 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001941
1942 audio_extn_dts_create_state_notifier_node(out->usecase);
1943 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1944 popcount(out->channel_mask),
1945 out->playback_started);
1946
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001947 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001948 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301951error:
Eric Laurent994a6932013-07-17 11:51:42 -07001952 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 return ret;
1954}
1955
1956static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1957{
1958 struct stream_out *out = (struct stream_out *)stream;
1959 struct str_parms *query = str_parms_create_str(keys);
1960 char *str;
1961 char value[256];
1962 struct str_parms *reply = str_parms_create();
1963 size_t i, j;
1964 int ret;
1965 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001966
1967 if (!query || !reply) {
1968 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1969 return NULL;
1970 }
1971
Eric Laurent994a6932013-07-17 11:51:42 -07001972 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1974 if (ret >= 0) {
1975 value[0] = '\0';
1976 i = 0;
1977 while (out->supported_channel_masks[i] != 0) {
1978 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1979 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1980 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001981 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001983 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 first = false;
1985 break;
1986 }
1987 }
1988 i++;
1989 }
1990 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1991 str = str_parms_to_str(reply);
1992 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001993 voice_extn_out_get_parameters(out, query, reply);
1994 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001995 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001996 free(str);
1997 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001998 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002000
2001 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2002 if (ret >= 0) {
2003 value[0] = '\0';
2004 i = 0;
2005 first = true;
2006 while (out->supported_formats[i] != 0) {
2007 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2008 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2009 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002010 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002011 }
2012 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2013 first = false;
2014 break;
2015 }
2016 }
2017 i++;
2018 }
2019 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2020 str = str_parms_to_str(reply);
2021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 str_parms_destroy(query);
2023 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002024 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025 return str;
2026}
2027
2028static uint32_t out_get_latency(const struct audio_stream_out *stream)
2029{
2030 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002031 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032
Alexy Josephaa54c872014-12-03 02:46:47 -08002033 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002034 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002035 } else {
2036 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002038 }
2039
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302040 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002041 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042}
2043
2044static int out_set_volume(struct audio_stream_out *stream, float left,
2045 float right)
2046{
Eric Laurenta9024de2013-04-04 09:19:12 -07002047 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 int volume[2];
2049
Eric Laurenta9024de2013-04-04 09:19:12 -07002050 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2051 /* only take left channel into account: the API is for stereo anyway */
2052 out->muted = (left == 0.0f);
2053 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002054 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002055 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2056 /*
2057 * Set mute or umute on HDMI passthrough stream.
2058 * Only take left channel into account.
2059 * Mute is 0 and unmute 1
2060 */
2061 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2062 } else {
2063 char mixer_ctl_name[128];
2064 struct audio_device *adev = out->dev;
2065 struct mixer_ctl *ctl;
2066 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002067 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002069 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2070 "Compress Playback %d Volume", pcm_device_id);
2071 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2072 if (!ctl) {
2073 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2074 __func__, mixer_ctl_name);
2075 return -EINVAL;
2076 }
2077 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2078 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2079 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2080 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002081 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002082 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084 return -ENOSYS;
2085}
2086
2087static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2088 size_t bytes)
2089{
2090 struct stream_out *out = (struct stream_out *)stream;
2091 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302092 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002093 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302096
Naresh Tanniru80659832014-06-04 18:17:56 +05302097 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002098 // increase written size during SSR to avoid mismatch
2099 // with the written frames count in AF
2100 if (!is_offload_usecase(out->usecase))
2101 out->written += bytes / (out->config.channels * sizeof(short));
2102
Naresh Tanniru80659832014-06-04 18:17:56 +05302103 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302104 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302105 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302106 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002107 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302108 //during SSR for compress usecase we should return error to flinger
2109 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2110 pthread_mutex_unlock(&out->lock);
2111 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302112 }
2113 }
2114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002116 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002117 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002118 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2119 ret = voice_extn_compress_voip_start_output_stream(out);
2120 else
2121 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002122 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002123 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002125 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126 goto exit;
2127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002130 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002131 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002132 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002133 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002134 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2135 out->send_new_metadata = 0;
2136 }
2137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302139 if (ret < 0)
2140 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002141 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002142 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302143 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302145 } else if (-ENETRESET == ret) {
2146 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2147 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2148 pthread_mutex_unlock(&out->lock);
2149 out_standby(&out->stream.common);
2150 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302152 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002154 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 out->playback_started = 1;
2156 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002157
2158 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2159 popcount(out->channel_mask),
2160 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 }
2162 pthread_mutex_unlock(&out->lock);
2163 return ret;
2164 } else {
2165 if (out->pcm) {
2166 if (out->muted)
2167 memset((void *)buffer, 0, bytes);
2168 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002169 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2170 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2171 else
2172 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302173 if (ret < 0)
2174 ret = -errno;
2175 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002176 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 }
2179
2180exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302181 /* ToDo: There may be a corner case when SSR happens back to back during
2182 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302183 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302184 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302185 }
2186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 pthread_mutex_unlock(&out->lock);
2188
2189 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002190 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002191 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302192 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302193 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302194 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302195 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302196 out->standby = true;
2197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002199 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302200 out_get_sample_rate(&out->stream.common));
2201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 }
2203 return bytes;
2204}
2205
2206static int out_get_render_position(const struct audio_stream_out *stream,
2207 uint32_t *dsp_frames)
2208{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302210 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002211
2212 if (dsp_frames == NULL)
2213 return -EINVAL;
2214
2215 *dsp_frames = 0;
2216 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002217 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 pthread_mutex_lock(&out->lock);
2219 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302222 if (ret < 0)
2223 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 ALOGVV("%s rendered frames %d sample_rate %d",
2225 __func__, *dsp_frames, out->sample_rate);
2226 }
2227 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302228 if (-ENETRESET == ret) {
2229 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2230 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2231 return -EINVAL;
2232 } else if(ret < 0) {
2233 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2234 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302235 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2236 /*
2237 * Handle corner case where compress session is closed during SSR
2238 * and timestamp is queried
2239 */
2240 ALOGE(" ERROR: sound card not active, return error");
2241 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302242 } else {
2243 return 0;
2244 }
Zhou Song32a556e2015-05-05 10:46:56 +08002245 } else if (audio_is_linear_pcm(out->format)) {
2246 *dsp_frames = out->written;
2247 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 } else
2249 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250}
2251
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002252static int out_add_audio_effect(const struct audio_stream *stream __unused,
2253 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 return 0;
2256}
2257
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002258static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2259 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260{
2261 return 0;
2262}
2263
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002264static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2265 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266{
2267 return -EINVAL;
2268}
2269
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002270static int out_get_presentation_position(const struct audio_stream_out *stream,
2271 uint64_t *frames, struct timespec *timestamp)
2272{
2273 struct stream_out *out = (struct stream_out *)stream;
2274 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002275 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002276
2277 pthread_mutex_lock(&out->lock);
2278
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002279 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002280 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302281 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002282 &out->sample_rate);
2283 ALOGVV("%s rendered frames %ld sample_rate %d",
2284 __func__, dsp_frames, out->sample_rate);
2285 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302286 if (ret < 0)
2287 ret = -errno;
2288 if (-ENETRESET == ret) {
2289 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2290 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2291 ret = -EINVAL;
2292 } else
2293 ret = 0;
2294
Eric Laurent949a0892013-09-20 09:20:13 -07002295 /* this is the best we can do */
2296 clock_gettime(CLOCK_MONOTONIC, timestamp);
2297 }
2298 } else {
2299 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002300 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002301 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2302 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002303 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002304 // This adjustment accounts for buffering after app processor.
2305 // It is based on estimated DSP latency per use case, rather than exact.
2306 signed_frames -=
2307 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2308
Eric Laurent949a0892013-09-20 09:20:13 -07002309 // It would be unusual for this value to be negative, but check just in case ...
2310 if (signed_frames >= 0) {
2311 *frames = signed_frames;
2312 ret = 0;
2313 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002314 }
2315 }
2316 }
2317
2318 pthread_mutex_unlock(&out->lock);
2319
2320 return ret;
2321}
2322
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002323static int out_set_callback(struct audio_stream_out *stream,
2324 stream_callback_t callback, void *cookie)
2325{
2326 struct stream_out *out = (struct stream_out *)stream;
2327
2328 ALOGV("%s", __func__);
2329 pthread_mutex_lock(&out->lock);
2330 out->offload_callback = callback;
2331 out->offload_cookie = cookie;
2332 pthread_mutex_unlock(&out->lock);
2333 return 0;
2334}
2335
2336static int out_pause(struct audio_stream_out* stream)
2337{
2338 struct stream_out *out = (struct stream_out *)stream;
2339 int status = -ENOSYS;
2340 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002341 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002342 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 pthread_mutex_lock(&out->lock);
2344 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302345 struct audio_device *adev = out->dev;
2346 int snd_scard_state = get_snd_card_state(adev);
2347
2348 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2349 status = compress_pause(out->compr);
2350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002352
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302353 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002354 audio_extn_dts_notify_playback_state(out->usecase, 0,
2355 out->sample_rate, popcount(out->channel_mask),
2356 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 }
2358 pthread_mutex_unlock(&out->lock);
2359 }
2360 return status;
2361}
2362
2363static int out_resume(struct audio_stream_out* stream)
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 int status = -ENOSYS;
2367 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002368 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002369 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 status = 0;
2371 pthread_mutex_lock(&out->lock);
2372 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302373 struct audio_device *adev = out->dev;
2374 int snd_scard_state = get_snd_card_state(adev);
2375
2376 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2377 status = compress_resume(out->compr);
2378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002380
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302381 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002382 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2383 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 }
2385 pthread_mutex_unlock(&out->lock);
2386 }
2387 return status;
2388}
2389
2390static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2391{
2392 struct stream_out *out = (struct stream_out *)stream;
2393 int status = -ENOSYS;
2394 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002395 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002396 pthread_mutex_lock(&out->lock);
2397 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2398 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2399 else
2400 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2401 pthread_mutex_unlock(&out->lock);
2402 }
2403 return status;
2404}
2405
2406static int out_flush(struct audio_stream_out* stream)
2407{
2408 struct stream_out *out = (struct stream_out *)stream;
2409 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002410 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002411 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002412 pthread_mutex_lock(&out->lock);
2413 stop_compressed_output_l(out);
2414 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002415 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416 return 0;
2417 }
2418 return -ENOSYS;
2419}
2420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421/** audio_stream_in implementation **/
2422static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2423{
2424 struct stream_in *in = (struct stream_in *)stream;
2425
2426 return in->config.rate;
2427}
2428
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002429static int in_set_sample_rate(struct audio_stream *stream __unused,
2430 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431{
2432 return -ENOSYS;
2433}
2434
2435static size_t in_get_buffer_size(const struct audio_stream *stream)
2436{
2437 struct stream_in *in = (struct stream_in *)stream;
2438
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002439 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2440 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002441 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2442 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002443
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002444 return in->config.period_size *
2445 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446}
2447
2448static uint32_t in_get_channels(const struct audio_stream *stream)
2449{
2450 struct stream_in *in = (struct stream_in *)stream;
2451
2452 return in->channel_mask;
2453}
2454
2455static audio_format_t in_get_format(const struct audio_stream *stream)
2456{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002457 struct stream_in *in = (struct stream_in *)stream;
2458
2459 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460}
2461
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002462static int in_set_format(struct audio_stream *stream __unused,
2463 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464{
2465 return -ENOSYS;
2466}
2467
2468static int in_standby(struct audio_stream *stream)
2469{
2470 struct stream_in *in = (struct stream_in *)stream;
2471 struct audio_device *adev = in->dev;
2472 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302473 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2474 stream, in->usecase, use_case_table[in->usecase]);
2475
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002476 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2477 /* Ignore standby in case of voip call because the voip input
2478 * stream is closed in adev_close_input_stream()
2479 */
2480 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2481 return status;
2482 }
2483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002485 if (!in->standby && in->is_st_session) {
2486 ALOGD("%s: sound trigger pcm stop lab", __func__);
2487 audio_extn_sound_trigger_stop_lab(in);
2488 in->standby = 1;
2489 }
2490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002492 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002494 if (in->pcm) {
2495 pcm_close(in->pcm);
2496 in->pcm = NULL;
2497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002499 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 }
2501 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002502 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 return status;
2504}
2505
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002506static int in_dump(const struct audio_stream *stream __unused,
2507 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508{
2509 return 0;
2510}
2511
2512static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2513{
2514 struct stream_in *in = (struct stream_in *)stream;
2515 struct audio_device *adev = in->dev;
2516 struct str_parms *parms;
2517 char *str;
2518 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002519 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302521 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 parms = str_parms_create_str(kvpairs);
2523
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302524 if (!parms)
2525 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002527 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002528
2529 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2530 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 val = atoi(value);
2532 /* no audio source uses val == 0 */
2533 if ((in->source != val) && (val != 0)) {
2534 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002535 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2536 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2537 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2538 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002539 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002540 err = voice_extn_compress_voip_open_input_stream(in);
2541 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002542 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002543 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002544 }
2545 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 }
2547 }
2548
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002549 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2550 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002552 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 in->device = val;
2554 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002555 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002556 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 }
2558 }
2559
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002560done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002562 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563
2564 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302565error:
Eric Laurent994a6932013-07-17 11:51:42 -07002566 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 return ret;
2568}
2569
2570static char* in_get_parameters(const struct audio_stream *stream,
2571 const char *keys)
2572{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002573 struct stream_in *in = (struct stream_in *)stream;
2574 struct str_parms *query = str_parms_create_str(keys);
2575 char *str;
2576 char value[256];
2577 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002578
2579 if (!query || !reply) {
2580 ALOGE("in_get_parameters: failed to create query or reply");
2581 return NULL;
2582 }
2583
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002584 ALOGV("%s: enter: keys - %s", __func__, keys);
2585
2586 voice_extn_in_get_parameters(in, query, reply);
2587
2588 str = str_parms_to_str(reply);
2589 str_parms_destroy(query);
2590 str_parms_destroy(reply);
2591
2592 ALOGV("%s: exit: returns - %s", __func__, str);
2593 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594}
2595
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002596static int in_set_gain(struct audio_stream_in *stream __unused,
2597 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598{
2599 return 0;
2600}
2601
2602static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2603 size_t bytes)
2604{
2605 struct stream_in *in = (struct stream_in *)stream;
2606 struct audio_device *adev = in->dev;
2607 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302608 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302611
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002612 if (in->is_st_session) {
2613 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2614 /* Read from sound trigger HAL */
2615 audio_extn_sound_trigger_read(in, buffer, bytes);
2616 pthread_mutex_unlock(&in->lock);
2617 return bytes;
2618 }
2619
2620 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2621 ALOGD(" %s: sound card is not active/SSR state", __func__);
2622 ret= -EIO;;
2623 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624 }
2625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002627 pthread_mutex_lock(&adev->lock);
2628 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2629 ret = voice_extn_compress_voip_start_input_stream(in);
2630 else
2631 ret = start_input_stream(in);
2632 pthread_mutex_unlock(&adev->lock);
2633 if (ret != 0) {
2634 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 }
2636 in->standby = 0;
2637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638
2639 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002640 if (audio_extn_ssr_get_enabled() &&
2641 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002642 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002643 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2644 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002645 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2646 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002647 else
2648 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302649 if (ret < 0)
2650 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 }
2652
2653 /*
2654 * Instead of writing zeroes here, we could trust the hardware
2655 * to always provide zeroes when muted.
2656 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302657 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2658 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 memset(buffer, 0, bytes);
2660
2661exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302662 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302663 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002664 if (-ENETRESET == ret)
2665 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 pthread_mutex_unlock(&in->lock);
2668
2669 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302670 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302671 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302672 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302673 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302674 in->standby = true;
2675 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302676 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002678 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002679 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302680 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 }
2682 return bytes;
2683}
2684
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002685static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686{
2687 return 0;
2688}
2689
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002690static int add_remove_audio_effect(const struct audio_stream *stream,
2691 effect_handle_t effect,
2692 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002694 struct stream_in *in = (struct stream_in *)stream;
2695 int status = 0;
2696 effect_descriptor_t desc;
2697
2698 status = (*effect)->get_descriptor(effect, &desc);
2699 if (status != 0)
2700 return status;
2701
2702 pthread_mutex_lock(&in->lock);
2703 pthread_mutex_lock(&in->dev->lock);
2704 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2705 in->enable_aec != enable &&
2706 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2707 in->enable_aec = enable;
2708 if (!in->standby)
2709 select_devices(in->dev, in->usecase);
2710 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002711 if (in->enable_ns != enable &&
2712 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2713 in->enable_ns = enable;
2714 if (!in->standby)
2715 select_devices(in->dev, in->usecase);
2716 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002717 pthread_mutex_unlock(&in->dev->lock);
2718 pthread_mutex_unlock(&in->lock);
2719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720 return 0;
2721}
2722
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002723static int in_add_audio_effect(const struct audio_stream *stream,
2724 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
Eric Laurent994a6932013-07-17 11:51:42 -07002726 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002727 return add_remove_audio_effect(stream, effect, true);
2728}
2729
2730static int in_remove_audio_effect(const struct audio_stream *stream,
2731 effect_handle_t effect)
2732{
Eric Laurent994a6932013-07-17 11:51:42 -07002733 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002734 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735}
2736
2737static int adev_open_output_stream(struct audio_hw_device *dev,
2738 audio_io_handle_t handle,
2739 audio_devices_t devices,
2740 audio_output_flags_t flags,
2741 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002742 struct audio_stream_out **stream_out,
2743 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744{
2745 struct audio_device *adev = (struct audio_device *)dev;
2746 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002747 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002748 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302751
2752 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2753 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2754 ALOGE(" sound card is not active rejecting compress output open request");
2755 return -EINVAL;
2756 }
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2759
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302760 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2761 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2762 devices, flags, &out->stream);
2763
2764
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002765 if (!out) {
2766 return -ENOMEM;
2767 }
2768
Haynes Mathew George204045b2015-02-25 20:32:03 -08002769 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2770 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 if (devices == AUDIO_DEVICE_NONE)
2773 devices = AUDIO_DEVICE_OUT_SPEAKER;
2774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 out->flags = flags;
2776 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002777 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002778 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002779 out->sample_rate = config->sample_rate;
2780 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2781 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002782 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002783 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002784 out->non_blocking = 0;
2785 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786
2787 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302788 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2789 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002790 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2791 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2792
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002793 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002794 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2795 ret = read_hdmi_channel_masks(out);
2796
2797 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2798 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002800 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002801 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002802
2803 if (config->sample_rate == 0)
2804 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2805 if (config->channel_mask == 0)
2806 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2807
2808 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2811 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002813 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002815 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2816 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002817 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002818 ret = voice_extn_compress_voip_open_output_stream(out);
2819 if (ret != 0) {
2820 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2821 __func__, ret);
2822 goto error_open;
2823 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2825 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2826 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2827 ALOGE("%s: Unsupported Offload information", __func__);
2828 ret = -EINVAL;
2829 goto error_open;
2830 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002831
2832 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2833 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2834 ALOGV("read and update_pass through formats");
2835 ret = audio_extn_dolby_update_passt_formats(adev, out);
2836 if(ret != 0) {
2837 goto error_open;
2838 }
2839 if(config->offload_info.format == 0)
2840 config->offload_info.format = out->supported_formats[0];
2841 }
2842
Mingming Yin90310102013-11-13 16:57:00 -08002843 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002844 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 ALOGE("%s: Unsupported audio format", __func__);
2846 ret = -EINVAL;
2847 goto error_open;
2848 }
2849
2850 out->compr_config.codec = (struct snd_codec *)
2851 calloc(1, sizeof(struct snd_codec));
2852
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002853 if (!out->compr_config.codec) {
2854 ret = -ENOMEM;
2855 goto error_open;
2856 }
2857
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002858 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 if (config->offload_info.channel_mask)
2860 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002861 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002863 config->offload_info.channel_mask = config->channel_mask;
2864 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002865 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 out->sample_rate = config->offload_info.sample_rate;
2867
2868 out->stream.set_callback = out_set_callback;
2869 out->stream.pause = out_pause;
2870 out->stream.resume = out_resume;
2871 out->stream.drain = out_drain;
2872 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002873 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002875 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002876 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002877 audio_extn_dolby_get_snd_codec_id(adev, out,
2878 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002879 else
2880 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302882 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002883 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002884 platform_get_pcm_offload_buffer_size(&config->offload_info);
2885 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2886 out->compr_config.fragment_size =
2887 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002888 } else {
2889 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002890 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002891 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2893 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302894 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 out->compr_config.codec->bit_rate =
2896 config->offload_info.bit_rate;
2897 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002898 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302900 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002901 /*TODO: Do we need to change it for passthrough */
2902 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903
Mingming Yin3ee55c62014-08-04 14:23:35 -07002904 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2905 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002906 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2907 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002909 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2910
Mingming Yin3ee55c62014-08-04 14:23:35 -07002911 if (out->bit_width == 24) {
2912 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2913 }
2914
Amit Shekhar6f461b12014-08-01 14:52:58 -07002915 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302916 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002918 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2919 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002920
Sharad Sangleb27354b2015-06-18 15:58:55 +05302921 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002922 //this flag is set from framework only if its for PCM formats
2923 //no need to check for PCM format again
2924 out->non_blocking = 0;
2925 out->use_small_bufs = true;
2926 ALOGI("Keep write blocking for small buff: non_blockling %d",
2927 out->non_blocking);
2928 }
2929
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002930 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002931 out->offload_state = OFFLOAD_STATE_IDLE;
2932 out->playback_started = 0;
2933
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002934 audio_extn_dts_create_state_notifier_node(out->usecase);
2935
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 create_offload_callback_thread(out);
2937 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2938 __func__, config->offload_info.version,
2939 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002940 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002941 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002942 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2943 ret = voice_check_and_set_incall_music_usecase(adev, out);
2944 if (ret != 0) {
2945 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2946 __func__, ret);
2947 goto error_open;
2948 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002949 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2950 if (config->sample_rate == 0)
2951 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2952 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2953 config->sample_rate != 8000) {
2954 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2955 ret = -EINVAL;
2956 goto error_open;
2957 }
2958 out->sample_rate = config->sample_rate;
2959 out->config.rate = config->sample_rate;
2960 if (config->format == AUDIO_FORMAT_DEFAULT)
2961 config->format = AUDIO_FORMAT_PCM_16_BIT;
2962 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2963 config->format = AUDIO_FORMAT_PCM_16_BIT;
2964 ret = -EINVAL;
2965 goto error_open;
2966 }
2967 out->format = config->format;
2968 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2969 out->config = pcm_config_afe_proxy_playback;
2970 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002971 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002972 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2974 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002975 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002976 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2977 format = AUDIO_FORMAT_PCM_16_BIT;
2978 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2979 out->config = pcm_config_deep_buffer;
2980 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002981 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002982 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002983 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002984 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002985 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002986 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987 }
2988
Amit Shekhar1d896042014-10-03 13:16:09 -07002989 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2990 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002991 /* TODO remove this hardcoding and check why width is zero*/
2992 if (out->bit_width == 0)
2993 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002994 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2995 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002996 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05302997 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002998 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2999 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3000 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003001 if(adev->primary_output == NULL)
3002 adev->primary_output = out;
3003 else {
3004 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003005 ret = -EEXIST;
3006 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003007 }
3008 }
3009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 /* Check if this usecase is already existing */
3011 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003012 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3013 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003016 ret = -EEXIST;
3017 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 }
3019 pthread_mutex_unlock(&adev->lock);
3020
3021 out->stream.common.get_sample_rate = out_get_sample_rate;
3022 out->stream.common.set_sample_rate = out_set_sample_rate;
3023 out->stream.common.get_buffer_size = out_get_buffer_size;
3024 out->stream.common.get_channels = out_get_channels;
3025 out->stream.common.get_format = out_get_format;
3026 out->stream.common.set_format = out_set_format;
3027 out->stream.common.standby = out_standby;
3028 out->stream.common.dump = out_dump;
3029 out->stream.common.set_parameters = out_set_parameters;
3030 out->stream.common.get_parameters = out_get_parameters;
3031 out->stream.common.add_audio_effect = out_add_audio_effect;
3032 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3033 out->stream.get_latency = out_get_latency;
3034 out->stream.set_volume = out_set_volume;
3035 out->stream.write = out_write;
3036 out->stream.get_render_position = out_get_render_position;
3037 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003038 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003041 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003042 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
3044 config->format = out->stream.common.get_format(&out->stream.common);
3045 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3046 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3047
3048 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303049 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3050 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003051
3052 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3053 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3054 popcount(out->channel_mask), out->playback_started);
3055
Eric Laurent994a6932013-07-17 11:51:42 -07003056 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003058
3059error_open:
3060 free(out);
3061 *stream_out = NULL;
3062 ALOGD("%s: exit: ret %d", __func__, ret);
3063 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064}
3065
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003066static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 struct audio_stream_out *stream)
3068{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 struct stream_out *out = (struct stream_out *)stream;
3070 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003071 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303073 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3074
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303076 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003077 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303078 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 if(ret != 0)
3080 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3081 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003082 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003083 out_standby(&stream->common);
3084
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003085 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003086 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003088 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 if (out->compr_config.codec != NULL)
3090 free(out->compr_config.codec);
3091 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003092
3093 if (adev->voice_tx_output == out)
3094 adev->voice_tx_output = NULL;
3095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096 pthread_cond_destroy(&out->cond);
3097 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003099 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100}
3101
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003102static void close_compress_sessions(struct audio_device *adev)
3103{
Mingming Yin7b762e72015-03-04 13:47:32 -08003104 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303105 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003106 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003107 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303108
3109 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003110 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303111 if (is_offload_usecase(usecase->id)) {
3112 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003113 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3114 out = usecase->stream.out;
3115 pthread_mutex_unlock(&adev->lock);
3116 out_standby(&out->stream.common);
3117 pthread_mutex_lock(&adev->lock);
3118 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303119 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003120 }
3121 pthread_mutex_unlock(&adev->lock);
3122}
3123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3125{
3126 struct audio_device *adev = (struct audio_device *)dev;
3127 struct str_parms *parms;
3128 char *str;
3129 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003130 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003131 int ret;
3132 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003134 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303137 if (!parms)
3138 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003139 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3140 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303141 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303142 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303143 struct listnode *node;
3144 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303146 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003147 //close compress sessions on OFFLINE status
3148 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303149 } else if (strstr(snd_card_status, "ONLINE")) {
3150 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303151 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303152 if (!platform_is_acdb_initialized(adev->platform)) {
3153 ret = platform_acdb_init(adev->platform);
3154 if(ret)
3155 ALOGE("acdb initialization is failed");
3156
3157 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303159 }
3160
3161 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003162 status = voice_set_parameters(adev, parms);
3163 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003164 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003166 status = platform_set_parameters(adev->platform, parms);
3167 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003168 goto done;
3169
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003170 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3171 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003172 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3174 adev->bluetooth_nrec = true;
3175 else
3176 adev->bluetooth_nrec = false;
3177 }
3178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3180 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3182 adev->screen_off = false;
3183 else
3184 adev->screen_off = true;
3185 }
3186
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003187 ret = str_parms_get_int(parms, "rotation", &val);
3188 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003189 bool reverse_speakers = false;
3190 switch(val) {
3191 // FIXME: note that the code below assumes that the speakers are in the correct placement
3192 // relative to the user when the device is rotated 90deg from its default rotation. This
3193 // assumption is device-specific, not platform-specific like this code.
3194 case 270:
3195 reverse_speakers = true;
3196 break;
3197 case 0:
3198 case 90:
3199 case 180:
3200 break;
3201 default:
3202 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003203 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003204 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003205 if (status == 0) {
3206 if (adev->speaker_lr_swap != reverse_speakers) {
3207 adev->speaker_lr_swap = reverse_speakers;
3208 // only update the selected device if there is active pcm playback
3209 struct audio_usecase *usecase;
3210 struct listnode *node;
3211 list_for_each(node, &adev->usecase_list) {
3212 usecase = node_to_item(node, struct audio_usecase, list);
3213 if (usecase->type == PCM_PLAYBACK) {
3214 select_devices(adev, usecase->id);
3215 break;
3216 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003217 }
3218 }
3219 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003220 }
3221
Mingming Yin514a8bc2014-07-29 15:22:21 -07003222 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3223 if (ret >= 0) {
3224 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3225 adev->bt_wb_speech_enabled = true;
3226 else
3227 adev->bt_wb_speech_enabled = false;
3228 }
3229
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003230 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3231 if (ret >= 0) {
3232 val = atoi(value);
3233 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3234 ALOGV("cache new edid");
3235 platform_cache_edid(adev->platform);
3236 }
3237 }
3238
3239 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3240 if (ret >= 0) {
3241 val = atoi(value);
3242 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3243 ALOGV("invalidate cached edid");
3244 platform_invalidate_edid(adev->platform);
3245 }
3246 }
3247
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003248 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003249
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003250done:
3251 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003252 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303253error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003254 ALOGV("%s: exit with code(%d)", __func__, status);
3255 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256}
3257
3258static char* adev_get_parameters(const struct audio_hw_device *dev,
3259 const char *keys)
3260{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003261 struct audio_device *adev = (struct audio_device *)dev;
3262 struct str_parms *reply = str_parms_create();
3263 struct str_parms *query = str_parms_create_str(keys);
3264 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303265 char value[256] = {0};
3266 int ret = 0;
3267
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003268 if (!query || !reply) {
3269 ALOGE("adev_get_parameters: failed to create query or reply");
3270 return NULL;
3271 }
3272
Naresh Tannirud7205b62014-06-20 02:54:48 +05303273 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3274 sizeof(value));
3275 if (ret >=0) {
3276 int val = 1;
3277 pthread_mutex_lock(&adev->snd_card_status.lock);
3278 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3279 val = 0;
3280 pthread_mutex_unlock(&adev->snd_card_status.lock);
3281 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3282 goto exit;
3283 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003284
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003285 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003286 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003287 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003288 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303289 pthread_mutex_unlock(&adev->lock);
3290
Naresh Tannirud7205b62014-06-20 02:54:48 +05303291exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003292 str = str_parms_to_str(reply);
3293 str_parms_destroy(query);
3294 str_parms_destroy(reply);
3295
3296 ALOGV("%s: exit: returns - %s", __func__, str);
3297 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298}
3299
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003300static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301{
3302 return 0;
3303}
3304
3305static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3306{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003307 int ret;
3308 struct audio_device *adev = (struct audio_device *)dev;
3309 pthread_mutex_lock(&adev->lock);
3310 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003311 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003312 pthread_mutex_unlock(&adev->lock);
3313 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314}
3315
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003316static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3317 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318{
3319 return -ENOSYS;
3320}
3321
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003322static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3323 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324{
3325 return -ENOSYS;
3326}
3327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003328static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3329 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330{
3331 return -ENOSYS;
3332}
3333
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003334static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3335 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336{
3337 return -ENOSYS;
3338}
3339
3340static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3341{
3342 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344 pthread_mutex_lock(&adev->lock);
3345 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003346 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003348 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3349 voice_is_in_call(adev)) {
3350 voice_stop_call(adev);
3351 adev->current_call_output = NULL;
3352 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 }
3354 pthread_mutex_unlock(&adev->lock);
3355 return 0;
3356}
3357
3358static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3359{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003360 int ret;
3361
3362 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003363 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003364 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3365 pthread_mutex_unlock(&adev->lock);
3366
3367 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368}
3369
3370static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3371{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003372 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373 return 0;
3374}
3375
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003376static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 const struct audio_config *config)
3378{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003379 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003381 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3382 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383}
3384
3385static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003386 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 audio_devices_t devices,
3388 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003389 struct audio_stream_in **stream_in,
3390 audio_input_flags_t flags __unused,
3391 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003392 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393{
3394 struct audio_device *adev = (struct audio_device *)dev;
3395 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003396 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003397 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003398 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 *stream_in = NULL;
3401 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3402 return -EINVAL;
3403
3404 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003405
3406 if (!in) {
3407 ALOGE("failed to allocate input stream");
3408 return -ENOMEM;
3409 }
3410
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303411 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003412 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3413 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003415 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 in->stream.common.get_sample_rate = in_get_sample_rate;
3418 in->stream.common.set_sample_rate = in_set_sample_rate;
3419 in->stream.common.get_buffer_size = in_get_buffer_size;
3420 in->stream.common.get_channels = in_get_channels;
3421 in->stream.common.get_format = in_get_format;
3422 in->stream.common.set_format = in_set_format;
3423 in->stream.common.standby = in_standby;
3424 in->stream.common.dump = in_dump;
3425 in->stream.common.set_parameters = in_set_parameters;
3426 in->stream.common.get_parameters = in_get_parameters;
3427 in->stream.common.add_audio_effect = in_add_audio_effect;
3428 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3429 in->stream.set_gain = in_set_gain;
3430 in->stream.read = in_read;
3431 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3432
3433 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003434 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003436 in->standby = 1;
3437 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003438 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439
3440 /* Update config params with the requested sample rate and channels */
3441 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003442 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3443 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3444 is_low_latency = true;
3445#if LOW_LATENCY_CAPTURE_USE_CASE
3446 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3447#endif
3448 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003451 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003453 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303454 if (adev->mode != AUDIO_MODE_IN_CALL) {
3455 ret = -EINVAL;
3456 goto err_open;
3457 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003458 if (config->sample_rate == 0)
3459 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3460 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3461 config->sample_rate != 8000) {
3462 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3463 ret = -EINVAL;
3464 goto err_open;
3465 }
3466 if (config->format == AUDIO_FORMAT_DEFAULT)
3467 config->format = AUDIO_FORMAT_PCM_16_BIT;
3468 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3469 config->format = AUDIO_FORMAT_PCM_16_BIT;
3470 ret = -EINVAL;
3471 goto err_open;
3472 }
3473
3474 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3475 in->config = pcm_config_afe_proxy_record;
3476 in->config.channels = channel_count;
3477 in->config.rate = config->sample_rate;
3478 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003480 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003481 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3482 ret = -EINVAL;
3483 goto err_open;
3484 }
3485 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003486 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003487 }
Mingming Yine62d7842013-10-25 16:26:03 -07003488 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003489 audio_extn_compr_cap_format_supported(config->format) &&
3490 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003491 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003492 } else {
3493 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003494 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003495 buffer_size = get_input_buffer_size(config->sample_rate,
3496 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003497 channel_count,
3498 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003499 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003500 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3501 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3502 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3503 (in->config.rate == 8000 || in->config.rate == 16000) &&
3504 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3505 voice_extn_compress_voip_open_input_stream(in);
3506 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003509 /* This stream could be for sound trigger lab,
3510 get sound trigger pcm if present */
3511 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303512 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003515 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003516 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517
3518err_open:
3519 free(in);
3520 *stream_in = NULL;
3521 return ret;
3522}
3523
3524static void adev_close_input_stream(struct audio_hw_device *dev,
3525 struct audio_stream_in *stream)
3526{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003527 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003528 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003529 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303530
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303531 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003532
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303533 /* Disable echo reference while closing input stream */
3534 platform_set_echo_reference(adev->platform, false);
3535
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003536 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303537 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003538 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303539 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003540 if (ret != 0)
3541 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3542 __func__, ret);
3543 } else
3544 in_standby(&stream->common);
3545
Mingming Yin7b762e72015-03-04 13:47:32 -08003546 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003547 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003548 audio_extn_ssr_deinit();
3549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550
Mingming Yine62d7842013-10-25 16:26:03 -07003551 if(audio_extn_compr_cap_enabled() &&
3552 audio_extn_compr_cap_format_supported(in->config.format))
3553 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003554
3555 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 return;
3557}
3558
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003559static int adev_dump(const audio_hw_device_t *device __unused,
3560 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561{
3562 return 0;
3563}
3564
3565static int adev_close(hw_device_t *device)
3566{
3567 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003568
3569 if (!adev)
3570 return 0;
3571
3572 pthread_mutex_lock(&adev_init_lock);
3573
3574 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003575 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003576 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003577 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003578 audio_route_free(adev->audio_route);
3579 free(adev->snd_dev_ref_cnt);
3580 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003581 free(device);
3582 adev = NULL;
3583 }
3584 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 return 0;
3586}
3587
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003588/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3589 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3590 * just that it _might_ work.
3591 */
3592static int period_size_is_plausible_for_low_latency(int period_size)
3593{
3594 switch (period_size) {
3595 case 160:
3596 case 240:
3597 case 320:
3598 case 480:
3599 return 1;
3600 default:
3601 return 0;
3602 }
3603}
3604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605static int adev_open(const hw_module_t *module, const char *name,
3606 hw_device_t **device)
3607{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003608 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003610 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3612
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003613 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003614 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003615 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003616 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003617 ALOGD("%s: returning existing instance of adev", __func__);
3618 ALOGD("%s: exit", __func__);
3619 pthread_mutex_unlock(&adev_init_lock);
3620 return 0;
3621 }
3622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 adev = calloc(1, sizeof(struct audio_device));
3624
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003625 if (!adev) {
3626 pthread_mutex_unlock(&adev_init_lock);
3627 return -ENOMEM;
3628 }
3629
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003630 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3633 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3634 adev->device.common.module = (struct hw_module_t *)module;
3635 adev->device.common.close = adev_close;
3636
3637 adev->device.init_check = adev_init_check;
3638 adev->device.set_voice_volume = adev_set_voice_volume;
3639 adev->device.set_master_volume = adev_set_master_volume;
3640 adev->device.get_master_volume = adev_get_master_volume;
3641 adev->device.set_master_mute = adev_set_master_mute;
3642 adev->device.get_master_mute = adev_get_master_mute;
3643 adev->device.set_mode = adev_set_mode;
3644 adev->device.set_mic_mute = adev_set_mic_mute;
3645 adev->device.get_mic_mute = adev_get_mic_mute;
3646 adev->device.set_parameters = adev_set_parameters;
3647 adev->device.get_parameters = adev_get_parameters;
3648 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3649 adev->device.open_output_stream = adev_open_output_stream;
3650 adev->device.close_output_stream = adev_close_output_stream;
3651 adev->device.open_input_stream = adev_open_input_stream;
3652 adev->device.close_input_stream = adev_close_input_stream;
3653 adev->device.dump = adev_dump;
3654
3655 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003657 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003658 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003661 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003662 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003663 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003664 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003665 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003666 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003667 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303668
3669 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3670 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003672 adev->platform = platform_init(adev);
3673 if (!adev->platform) {
3674 free(adev->snd_dev_ref_cnt);
3675 free(adev);
3676 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3677 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003678 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003679 return -EINVAL;
3680 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003681
Naresh Tanniru4c630392014-05-12 01:05:52 +05303682 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3683
Eric Laurentc4aef752013-09-12 17:45:53 -07003684 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3685 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3686 if (adev->visualizer_lib == NULL) {
3687 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3688 } else {
3689 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3690 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003691 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003692 "visualizer_hal_start_output");
3693 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003694 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003695 "visualizer_hal_stop_output");
3696 }
3697 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003698 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003699 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003700
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003701 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3702 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3703 if (adev->offload_effects_lib == NULL) {
3704 ALOGE("%s: DLOPEN failed for %s", __func__,
3705 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3706 } else {
3707 ALOGV("%s: DLOPEN successful for %s", __func__,
3708 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3709 adev->offload_effects_start_output =
3710 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3711 "offload_effects_bundle_hal_start_output");
3712 adev->offload_effects_stop_output =
3713 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3714 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003715 adev->offload_effects_set_hpx_state =
3716 (int (*)(bool))dlsym(adev->offload_effects_lib,
3717 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003718 }
3719 }
3720
Mingming Yin514a8bc2014-07-29 15:22:21 -07003721 adev->bt_wb_speech_enabled = false;
3722
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003723 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 *device = &adev->device.common;
3725
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003726 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3727 &adev->streams_output_cfg_list);
3728
Kiran Kandi910e1862013-10-29 13:29:42 -07003729 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003730
3731 char value[PROPERTY_VALUE_MAX];
3732 int trial;
3733 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3734 trial = atoi(value);
3735 if (period_size_is_plausible_for_low_latency(trial)) {
3736 pcm_config_low_latency.period_size = trial;
3737 pcm_config_low_latency.start_threshold = trial / 4;
3738 pcm_config_low_latency.avail_min = trial / 4;
3739 configured_low_latency_capture_period_size = trial;
3740 }
3741 }
3742 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3743 trial = atoi(value);
3744 if (period_size_is_plausible_for_low_latency(trial)) {
3745 configured_low_latency_capture_period_size = trial;
3746 }
3747 }
3748
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003749 pthread_mutex_unlock(&adev_init_lock);
3750
Eric Laurent994a6932013-07-17 11:51:42 -07003751 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 return 0;
3753}
3754
3755static struct hw_module_methods_t hal_module_methods = {
3756 .open = adev_open,
3757};
3758
3759struct audio_module HAL_MODULE_INFO_SYM = {
3760 .common = {
3761 .tag = HARDWARE_MODULE_TAG,
3762 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3763 .hal_api_version = HARDWARE_HAL_API_VERSION,
3764 .id = AUDIO_HARDWARE_MODULE_ID,
3765 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003766 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 .methods = &hal_module_methods,
3768 },
3769};