blob: f97efddae03677c13837bfc06f637aac72ccf766 [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);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530661 /* Update the out_snd_device only for the usecases that are enabled here */
662 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
663 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530664 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 }
666 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 }
668}
669
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670static void check_and_route_capture_usecases(struct audio_device *adev,
671 struct audio_usecase *uc_info,
672 snd_device_t snd_device)
673{
674 struct listnode *node;
675 struct audio_usecase *usecase;
676 bool switch_device[AUDIO_USECASE_MAX];
677 int i, num_uc_to_switch = 0;
678
679 /*
680 * This function is to make sure that all the active capture usecases
681 * are always routed to the same input sound device.
682 * For example, if audio-record and voice-call usecases are currently
683 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
684 * is received for voice call then we have to make sure that audio-record
685 * usecase is also switched to earpiece i.e. voice-dmic-ef,
686 * because of the limitation that two devices cannot be enabled
687 * at the same time if they share the same backend.
688 */
689 for (i = 0; i < AUDIO_USECASE_MAX; i++)
690 switch_device[i] = false;
691
692 list_for_each(node, &adev->usecase_list) {
693 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800694 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700696 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530697 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700698 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700699 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
700 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700701 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 switch_device[usecase->id] = true;
704 num_uc_to_switch++;
705 }
706 }
707
708 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700709 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530711 /* Make sure the previous devices to be disabled first and then enable the
712 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700713 list_for_each(node, &adev->usecase_list) {
714 usecase = node_to_item(node, struct audio_usecase, list);
715 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700716 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 }
718 }
719
720 list_for_each(node, &adev->usecase_list) {
721 usecase = node_to_item(node, struct audio_usecase, list);
722 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700723 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 }
725 }
726
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 /* Re-route all the usecases on the shared backend other than the
728 specified usecase to new snd devices */
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 /* Update the in_snd_device only before enabling the audio route */
732 if (switch_device[usecase->id] ) {
733 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800734 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530735 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 }
737 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 }
739}
740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700742static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700744 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700745 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746
747 switch (channels) {
748 /*
749 * Do not handle stereo output in Multi-channel cases
750 * Stereo case is handled in normal playback path
751 */
752 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700753 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
754 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
757 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800759 break;
760 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700761 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 break;
769 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700770 ALOGE("HDMI does not support multi channel playback");
771 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772 break;
773 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700774 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775}
776
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800777audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
778 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700779{
780 struct audio_usecase *usecase;
781 struct listnode *node;
782
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800785 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700786 ALOGV("%s: usecase id %d", __func__, usecase->id);
787 return usecase->id;
788 }
789 }
790 return USECASE_INVALID;
791}
792
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700793struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700794 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795{
796 struct audio_usecase *usecase;
797 struct listnode *node;
798
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
801 if (usecase->id == uc_id)
802 return usecase;
803 }
804 return NULL;
805}
806
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700807int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800809 snd_device_t out_snd_device = SND_DEVICE_NONE;
810 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811 struct audio_usecase *usecase = NULL;
812 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800813 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800814 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800815 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800816 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 usecase = get_usecase_from_list(adev, uc_id);
820 if (usecase == NULL) {
821 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
822 return -EINVAL;
823 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800825 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800826 (usecase->type == VOIP_CALL) ||
827 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700828 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800829 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700830 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 usecase->devices = usecase->stream.out->devices;
832 } else {
833 /*
834 * If the voice call is active, use the sound devices of voice call usecase
835 * so that it would not result any device switch. All the usecases will
836 * be switched to new device when select_devices() is called for voice call
837 * usecase. This is to avoid switching devices for voice call when
838 * check_usecases_codec_backend() is called below.
839 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700840 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700841 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800842 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700843 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
844 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 in_snd_device = vc_usecase->in_snd_device;
846 out_snd_device = vc_usecase->out_snd_device;
847 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800848 } else if (voice_extn_compress_voip_is_active(adev)) {
849 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700850 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530851 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700852 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800853 in_snd_device = voip_usecase->in_snd_device;
854 out_snd_device = voip_usecase->out_snd_device;
855 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800856 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800857 hfp_ucid = audio_extn_hfp_get_usecase();
858 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800860 in_snd_device = hfp_usecase->in_snd_device;
861 out_snd_device = hfp_usecase->out_snd_device;
862 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 }
864 if (usecase->type == PCM_PLAYBACK) {
865 usecase->devices = usecase->stream.out->devices;
866 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700867 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800869 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700870 if (usecase->stream.out == adev->primary_output &&
871 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800872 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700873 select_devices(adev, adev->active_input->usecase);
874 }
875 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 } else if (usecase->type == PCM_CAPTURE) {
877 usecase->devices = usecase->stream.in->device;
878 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700879 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700880 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530881 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
882 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
883 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
884 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700885 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800886 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700887 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
888 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700889 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700890 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700891 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 }
893 }
894
895 if (out_snd_device == usecase->out_snd_device &&
896 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800897 return 0;
898 }
899
sangwoobc677242013-08-08 16:53:43 +0900900 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 out_snd_device, platform_get_snd_device_name(out_snd_device),
902 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800904 /*
905 * Limitation: While in call, to do a device switch we need to disable
906 * and enable both RX and TX devices though one of them is same as current
907 * device.
908 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700909 if ((usecase->type == VOICE_CALL) &&
910 (usecase->in_snd_device != SND_DEVICE_NONE) &&
911 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700912 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700913 /* Disable sidetone only if voice call already exists */
914 if (voice_is_call_state_active(adev))
915 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800916 }
917
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 /* Disable current sound devices */
919 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700920 disable_audio_route(adev, usecase);
921 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800922 }
923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700924 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700925 disable_audio_route(adev, usecase);
926 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927 }
928
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800929 /* Applicable only on the targets that has external modem.
930 * New device information should be sent to modem before enabling
931 * the devices to reduce in-call device switch time.
932 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700933 if ((usecase->type == VOICE_CALL) &&
934 (usecase->in_snd_device != SND_DEVICE_NONE) &&
935 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800936 status = platform_switch_voice_call_enable_device_config(adev->platform,
937 out_snd_device,
938 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700939 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 /* Enable new sound devices */
942 if (out_snd_device != SND_DEVICE_NONE) {
943 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
944 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700945 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946 }
947
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700948 if (in_snd_device != SND_DEVICE_NONE) {
949 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700950 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952
Avinash Vaish71a8b972014-07-24 15:36:33 +0530953 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700954 status = platform_switch_voice_call_device_post(adev->platform,
955 out_snd_device,
956 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530957 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700958 /* Enable sidetone only if voice call already exists */
959 if (voice_is_call_state_active(adev))
960 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530961 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800962
sangwoo170731f2013-06-08 15:36:36 +0900963 usecase->in_snd_device = in_snd_device;
964 usecase->out_snd_device = out_snd_device;
965
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530966 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700967 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530968 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700969 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530970 usecase->stream.out->flags,
971 usecase->stream.out->format,
972 usecase->stream.out->sample_rate,
973 usecase->stream.out->bit_width,
974 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700975 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530976 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700977
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700978 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900979
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800980 /* Applicable only on the targets that has external modem.
981 * Enable device command should be sent to modem only after
982 * enabling voice call mixer controls
983 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700984 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800985 status = platform_switch_voice_call_usecase_route_post(adev->platform,
986 out_snd_device,
987 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530988 ALOGD("%s: done",__func__);
989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 return status;
991}
992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993static int stop_input_stream(struct stream_in *in)
994{
995 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996 struct audio_usecase *uc_info;
997 struct audio_device *adev = in->dev;
998
Eric Laurentc8400632013-02-14 19:04:54 -0800999 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000
Eric Laurent994a6932013-07-17 11:51:42 -07001001 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001002 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003 uc_info = get_usecase_from_list(adev, in->usecase);
1004 if (uc_info == NULL) {
1005 ALOGE("%s: Could not find the usecase (%d) in the list",
1006 __func__, in->usecase);
1007 return -EINVAL;
1008 }
1009
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001010 /* Close in-call recording streams */
1011 voice_check_and_stop_incall_rec_usecase(adev, in);
1012
Eric Laurent150dbfe2013-02-27 14:31:02 -08001013 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001014 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001015
1016 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001017 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001019 list_remove(&uc_info->list);
1020 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021
Eric Laurent994a6932013-07-17 11:51:42 -07001022 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001023 return ret;
1024}
1025
1026int start_input_stream(struct stream_in *in)
1027{
1028 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001029 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030 struct audio_usecase *uc_info;
1031 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301032 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033
Mingming Yine62d7842013-10-25 16:26:03 -07001034 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301035 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1036 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001037
Naresh Tanniru80659832014-06-04 18:17:56 +05301038
1039 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301040 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301041 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301042 goto error_config;
1043 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301044
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001045 /* Check if source matches incall recording usecase criteria */
1046 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1047 if (ret)
1048 goto error_config;
1049 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001050 ALOGD("%s: Updated usecase(%d: %s)",
1051 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001052
Eric Laurentb23d5282013-05-14 15:27:20 -07001053 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 if (in->pcm_device_id < 0) {
1055 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1056 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001057 ret = -EINVAL;
1058 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060
1061 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001063
1064 if (!uc_info) {
1065 ret = -ENOMEM;
1066 goto error_config;
1067 }
1068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069 uc_info->id = in->usecase;
1070 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001071 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 uc_info->devices = in->device;
1073 uc_info->in_snd_device = SND_DEVICE_NONE;
1074 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001076 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301077 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001078 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079
Eric Laurentc8400632013-02-14 19:04:54 -08001080 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001081 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1082
1083 unsigned int flags = PCM_IN;
1084 unsigned int pcm_open_retry_count = 0;
1085
1086 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1087 flags |= PCM_MMAP | PCM_NOIRQ;
1088 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1089 }
1090
1091 while (1) {
1092 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1093 flags, &in->config);
1094 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1095 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1096 if (in->pcm != NULL) {
1097 pcm_close(in->pcm);
1098 in->pcm = NULL;
1099 }
1100 if (pcm_open_retry_count-- == 0) {
1101 ret = -EIO;
1102 goto error_open;
1103 }
1104 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1105 continue;
1106 }
1107 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301109 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301110
Eric Laurent994a6932013-07-17 11:51:42 -07001111 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001112 return ret;
1113
1114error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301116 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001117
1118error_config:
1119 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001121
1122 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001123}
1124
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001125/* must be called with out->lock locked */
1126static int send_offload_cmd_l(struct stream_out* out, int command)
1127{
1128 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1129
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001130 if (!cmd) {
1131 ALOGE("failed to allocate mem for command 0x%x", command);
1132 return -ENOMEM;
1133 }
1134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001135 ALOGVV("%s %d", __func__, command);
1136
1137 cmd->cmd = command;
1138 list_add_tail(&out->offload_cmd_list, &cmd->node);
1139 pthread_cond_signal(&out->offload_cond);
1140 return 0;
1141}
1142
1143/* must be called iwth out->lock locked */
1144static void stop_compressed_output_l(struct stream_out *out)
1145{
1146 out->offload_state = OFFLOAD_STATE_IDLE;
1147 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001148 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001149 if (out->compr != NULL) {
1150 compress_stop(out->compr);
1151 while (out->offload_thread_blocked) {
1152 pthread_cond_wait(&out->cond, &out->lock);
1153 }
1154 }
1155}
1156
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001157bool is_offload_usecase(audio_usecase_t uc_id)
1158{
1159 unsigned int i;
1160 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1161 if (uc_id == offload_usecases[i])
1162 return true;
1163 }
1164 return false;
1165}
1166
1167static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1168{
1169 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1170 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1171 char value[PROPERTY_VALUE_MAX] = {0};
1172
1173 property_get("audio.offload.multiple.enabled", value, NULL);
1174 if (!(atoi(value) || !strncmp("true", value, 4)))
1175 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1176
1177 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1178 for (i = 0; i < num_usecase; i++) {
1179 if (!(adev->offload_usecases_state & (0x1<<i))) {
1180 adev->offload_usecases_state |= 0x1 << i;
1181 ret = offload_usecases[i];
1182 break;
1183 }
1184 }
1185 ALOGV("%s: offload usecase is %d", __func__, ret);
1186 return ret;
1187}
1188
1189static void free_offload_usecase(struct audio_device *adev,
1190 audio_usecase_t uc_id)
1191{
1192 unsigned int i;
1193 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1194 if (offload_usecases[i] == uc_id) {
1195 adev->offload_usecases_state &= ~(0x1<<i);
1196 break;
1197 }
1198 }
1199 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1200}
1201
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001202static void *offload_thread_loop(void *context)
1203{
1204 struct stream_out *out = (struct stream_out *) context;
1205 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001206 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001207
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001208 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1209 set_sched_policy(0, SP_FOREGROUND);
1210 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1211
1212 ALOGV("%s", __func__);
1213 pthread_mutex_lock(&out->lock);
1214 for (;;) {
1215 struct offload_cmd *cmd = NULL;
1216 stream_callback_event_t event;
1217 bool send_callback = false;
1218
1219 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1220 __func__, list_empty(&out->offload_cmd_list),
1221 out->offload_state);
1222 if (list_empty(&out->offload_cmd_list)) {
1223 ALOGV("%s SLEEPING", __func__);
1224 pthread_cond_wait(&out->offload_cond, &out->lock);
1225 ALOGV("%s RUNNING", __func__);
1226 continue;
1227 }
1228
1229 item = list_head(&out->offload_cmd_list);
1230 cmd = node_to_item(item, struct offload_cmd, node);
1231 list_remove(item);
1232
1233 ALOGVV("%s STATE %d CMD %d out->compr %p",
1234 __func__, out->offload_state, cmd->cmd, out->compr);
1235
1236 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1237 free(cmd);
1238 break;
1239 }
1240
1241 if (out->compr == NULL) {
1242 ALOGE("%s: Compress handle is NULL", __func__);
1243 pthread_cond_signal(&out->cond);
1244 continue;
1245 }
1246 out->offload_thread_blocked = true;
1247 pthread_mutex_unlock(&out->lock);
1248 send_callback = false;
1249 switch(cmd->cmd) {
1250 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001251 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001252 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001253 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001254 send_callback = true;
1255 event = STREAM_CBK_EVENT_WRITE_READY;
1256 break;
1257 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001258 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301259 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001260 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301261 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001262 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301263 if (ret < 0)
1264 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301265 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301266 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001267 compress_drain(out->compr);
1268 else
1269 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301270 if (ret != -ENETRESET) {
1271 send_callback = true;
1272 event = STREAM_CBK_EVENT_DRAIN_READY;
1273 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1274 } else
1275 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 break;
1277 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001278 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001279 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001280 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001281 send_callback = true;
1282 event = STREAM_CBK_EVENT_DRAIN_READY;
1283 break;
1284 default:
1285 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1286 break;
1287 }
1288 pthread_mutex_lock(&out->lock);
1289 out->offload_thread_blocked = false;
1290 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001291 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001292 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001293 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001294 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001295 free(cmd);
1296 }
1297
1298 pthread_cond_signal(&out->cond);
1299 while (!list_empty(&out->offload_cmd_list)) {
1300 item = list_head(&out->offload_cmd_list);
1301 list_remove(item);
1302 free(node_to_item(item, struct offload_cmd, node));
1303 }
1304 pthread_mutex_unlock(&out->lock);
1305
1306 return NULL;
1307}
1308
1309static int create_offload_callback_thread(struct stream_out *out)
1310{
1311 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1312 list_init(&out->offload_cmd_list);
1313 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1314 offload_thread_loop, out);
1315 return 0;
1316}
1317
1318static int destroy_offload_callback_thread(struct stream_out *out)
1319{
1320 pthread_mutex_lock(&out->lock);
1321 stop_compressed_output_l(out);
1322 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1323
1324 pthread_mutex_unlock(&out->lock);
1325 pthread_join(out->offload_thread, (void **) NULL);
1326 pthread_cond_destroy(&out->offload_cond);
1327
1328 return 0;
1329}
1330
Eric Laurent07eeafd2013-10-06 12:52:49 -07001331static bool allow_hdmi_channel_config(struct audio_device *adev)
1332{
1333 struct listnode *node;
1334 struct audio_usecase *usecase;
1335 bool ret = true;
1336
1337 list_for_each(node, &adev->usecase_list) {
1338 usecase = node_to_item(node, struct audio_usecase, list);
1339 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1340 /*
1341 * If voice call is already existing, do not proceed further to avoid
1342 * disabling/enabling both RX and TX devices, CSD calls, etc.
1343 * Once the voice call done, the HDMI channels can be configured to
1344 * max channels of remaining use cases.
1345 */
1346 if (usecase->id == USECASE_VOICE_CALL) {
1347 ALOGD("%s: voice call is active, no change in HDMI channels",
1348 __func__);
1349 ret = false;
1350 break;
1351 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1352 ALOGD("%s: multi channel playback is active, "
1353 "no change in HDMI channels", __func__);
1354 ret = false;
1355 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001356 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001357 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001358 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1359 ", no change in HDMI channels", __func__,
1360 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001361 ret = false;
1362 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001363 }
1364 }
1365 }
1366 return ret;
1367}
1368
1369static int check_and_set_hdmi_channels(struct audio_device *adev,
1370 unsigned int channels)
1371{
1372 struct listnode *node;
1373 struct audio_usecase *usecase;
1374
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001375 unsigned int supported_channels = platform_edid_get_max_channels(
1376 adev->platform);
1377 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001378 /* Check if change in HDMI channel config is allowed */
1379 if (!allow_hdmi_channel_config(adev))
1380 return 0;
1381
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001382 if (channels > supported_channels)
1383 channels = supported_channels;
1384
Eric Laurent07eeafd2013-10-06 12:52:49 -07001385 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001386 ALOGD("%s: Requested channels are same as current channels(%d)",
1387 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001388 return 0;
1389 }
1390
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001391 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001392 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001393 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001394 adev->cur_hdmi_channels = channels;
1395
1396 /*
1397 * Deroute all the playback streams routed to HDMI so that
1398 * the back end is deactivated. Note that backend will not
1399 * be deactivated if any one stream is connected to it.
1400 */
1401 list_for_each(node, &adev->usecase_list) {
1402 usecase = node_to_item(node, struct audio_usecase, list);
1403 if (usecase->type == PCM_PLAYBACK &&
1404 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001405 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001406 }
1407 }
1408
1409 /*
1410 * Enable all the streams disabled above. Now the HDMI backend
1411 * will be activated with new channel configuration
1412 */
1413 list_for_each(node, &adev->usecase_list) {
1414 usecase = node_to_item(node, struct audio_usecase, list);
1415 if (usecase->type == PCM_PLAYBACK &&
1416 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001417 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001418 }
1419 }
1420
1421 return 0;
1422}
1423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424static int stop_output_stream(struct stream_out *out)
1425{
1426 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 struct audio_usecase *uc_info;
1428 struct audio_device *adev = out->dev;
1429
Eric Laurent994a6932013-07-17 11:51:42 -07001430 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 uc_info = get_usecase_from_list(adev, out->usecase);
1433 if (uc_info == NULL) {
1434 ALOGE("%s: Could not find the usecase (%d) in the list",
1435 __func__, out->usecase);
1436 return -EINVAL;
1437 }
1438
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001439 if (is_offload_usecase(out->usecase) &&
1440 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001441 if (adev->visualizer_stop_output != NULL)
1442 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001443
1444 audio_extn_dts_remove_state_notifier_node(out->usecase);
1445
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001446 if (adev->offload_effects_stop_output != NULL)
1447 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1448 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001449
Eric Laurent150dbfe2013-02-27 14:31:02 -08001450 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001451 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452
1453 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001454 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001456 list_remove(&uc_info->list);
1457 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001459 if (is_offload_usecase(out->usecase) &&
1460 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1461 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1462 ALOGV("Disable passthrough , reset mixer to pcm");
1463 /* NO_PASSTHROUGH */
1464 out->compr_config.codec->compr_passthr = 0;
1465 audio_extn_dolby_set_hdmi_config(adev, out);
1466 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1467 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001468 /* Must be called after removing the usecase from list */
1469 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1470 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1471
Eric Laurent994a6932013-07-17 11:51:42 -07001472 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 return ret;
1474}
1475
1476int start_output_stream(struct stream_out *out)
1477{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001479 int sink_channels = 0;
1480 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 struct audio_usecase *uc_info;
1482 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301483 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001485 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1486 ret = -EINVAL;
1487 goto error_config;
1488 }
1489
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301490 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1491 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1492 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301493
Naresh Tanniru80659832014-06-04 18:17:56 +05301494 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301495 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301496 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301497 goto error_config;
1498 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301499
Eric Laurentb23d5282013-05-14 15:27:20 -07001500 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 if (out->pcm_device_id < 0) {
1502 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1503 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001504 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001505 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506 }
1507
1508 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001509
1510 if (!uc_info) {
1511 ret = -ENOMEM;
1512 goto error_config;
1513 }
1514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515 uc_info->id = out->usecase;
1516 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001517 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 uc_info->devices = out->devices;
1519 uc_info->in_snd_device = SND_DEVICE_NONE;
1520 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001521 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001522 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001523 if (is_offload_usecase(out->usecase)) {
1524 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001525 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1526 }
1527 }
Mingming Yin9c041392014-05-01 15:37:31 -07001528 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1529 if (!strncmp("true", prop_value, 4)) {
1530 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001531 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1532 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001533 check_and_set_hdmi_channels(adev, sink_channels);
1534 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001535 if (is_offload_usecase(out->usecase)) {
1536 unsigned int ch_count = out->compr_config.codec->ch_in;
1537 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1538 /* backend channel config for passthrough stream is stereo */
1539 ch_count = 2;
1540 check_and_set_hdmi_channels(adev, ch_count);
1541 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001542 check_and_set_hdmi_channels(adev, out->config.channels);
1543 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001544 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001545 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001546 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001548 select_devices(adev, out->usecase);
1549
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001550 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1551 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001552 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001553 unsigned int flags = PCM_OUT;
1554 unsigned int pcm_open_retry_count = 0;
1555 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1556 flags |= PCM_MMAP | PCM_NOIRQ;
1557 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1558 } else
1559 flags |= PCM_MONOTONIC;
1560
1561 while (1) {
1562 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1563 flags, &out->config);
1564 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1565 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1566 if (out->pcm != NULL) {
1567 pcm_close(out->pcm);
1568 out->pcm = NULL;
1569 }
1570 if (pcm_open_retry_count-- == 0) {
1571 ret = -EIO;
1572 goto error_open;
1573 }
1574 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1575 continue;
1576 }
1577 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001578 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001579 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1580 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001582 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1583 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001585 out->compr = compress_open(adev->snd_card,
1586 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001587 COMPRESS_IN, &out->compr_config);
1588 if (out->compr && !is_compress_ready(out->compr)) {
1589 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1590 compress_close(out->compr);
1591 out->compr = NULL;
1592 ret = -EIO;
1593 goto error_open;
1594 }
1595 if (out->offload_callback)
1596 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001597
Fred Oh3f43e742015-03-04 18:42:34 -08001598 /* Since small bufs uses blocking writes, a write will be blocked
1599 for the default max poll time (20s) in the event of an SSR.
1600 Reduce the poll time to observe and deal with SSR faster.
1601 */
1602 if (out->use_small_bufs) {
1603 compress_set_max_poll_wait(out->compr, 1000);
1604 }
1605
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001606 audio_extn_dts_create_state_notifier_node(out->usecase);
1607 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1608 popcount(out->channel_mask),
1609 out->playback_started);
1610
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001611#ifdef DS1_DOLBY_DDP_ENABLED
1612 if (audio_extn_is_dolby_format(out->format))
1613 audio_extn_dolby_send_ddp_endp_params(adev);
1614#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001615 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1616 if (adev->visualizer_start_output != NULL)
1617 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1618 if (adev->offload_effects_start_output != NULL)
1619 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001620 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 }
Eric Laurent994a6932013-07-17 11:51:42 -07001623 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001625error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001627error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001628 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629}
1630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631static int check_input_parameters(uint32_t sample_rate,
1632 audio_format_t format,
1633 int channel_count)
1634{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001635 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001637 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001638 !voice_extn_compress_voip_is_format_supported(format) &&
1639 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001640
1641 switch (channel_count) {
1642 case 1:
1643 case 2:
1644 case 6:
1645 break;
1646 default:
1647 ret = -EINVAL;
1648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
1650 switch (sample_rate) {
1651 case 8000:
1652 case 11025:
1653 case 12000:
1654 case 16000:
1655 case 22050:
1656 case 24000:
1657 case 32000:
1658 case 44100:
1659 case 48000:
1660 break;
1661 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001662 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 }
1664
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001665 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666}
1667
1668static size_t get_input_buffer_size(uint32_t sample_rate,
1669 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001670 int channel_count,
1671 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672{
1673 size_t size = 0;
1674
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001675 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1676 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001678 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001679 if (is_low_latency)
1680 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001681 /* ToDo: should use frame_size computed based on the format and
1682 channel_count here. */
1683 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001685 /* make sure the size is multiple of 32 bytes
1686 * At 48 kHz mono 16-bit PCM:
1687 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1688 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1689 */
1690 size += 0x1f;
1691 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001692
1693 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694}
1695
1696static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1697{
1698 struct stream_out *out = (struct stream_out *)stream;
1699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001700 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701}
1702
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001703static int out_set_sample_rate(struct audio_stream *stream __unused,
1704 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705{
1706 return -ENOSYS;
1707}
1708
1709static size_t out_get_buffer_size(const struct audio_stream *stream)
1710{
1711 struct stream_out *out = (struct stream_out *)stream;
1712
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001713 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001715 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1716 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001718 return out->config.period_size *
1719 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720}
1721
1722static uint32_t out_get_channels(const struct audio_stream *stream)
1723{
1724 struct stream_out *out = (struct stream_out *)stream;
1725
1726 return out->channel_mask;
1727}
1728
1729static audio_format_t out_get_format(const struct audio_stream *stream)
1730{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 struct stream_out *out = (struct stream_out *)stream;
1732
1733 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734}
1735
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001736static int out_set_format(struct audio_stream *stream __unused,
1737 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738{
1739 return -ENOSYS;
1740}
1741
1742static int out_standby(struct audio_stream *stream)
1743{
1744 struct stream_out *out = (struct stream_out *)stream;
1745 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301747 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1748 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001749 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1750 /* Ignore standby in case of voip call because the voip output
1751 * stream is closed in adev_close_output_stream()
1752 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301753 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001754 return 0;
1755 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001759 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001761 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 if (out->pcm) {
1763 pcm_close(out->pcm);
1764 out->pcm = NULL;
1765 }
1766 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001767 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001768 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001769 out->gapless_mdata.encoder_delay = 0;
1770 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 if (out->compr != NULL) {
1772 compress_close(out->compr);
1773 out->compr = NULL;
1774 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001777 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 }
1779 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001780 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 return 0;
1782}
1783
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001784static int out_dump(const struct audio_stream *stream __unused,
1785 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786{
1787 return 0;
1788}
1789
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001790static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1791{
1792 int ret = 0;
1793 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001794 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001795
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001796 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001797 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798 return -EINVAL;
1799 }
1800
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001801 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1802 if (ret >= 0) {
1803 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1804 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1805 ALOGV("ADTS format is set in offload mode");
1806 }
1807 out->send_new_metadata = 1;
1808 }
1809
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301810 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001811
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001812 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1813 if(ret >= 0)
1814 is_meta_data_params = true;
1815 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301816 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001817 is_meta_data_params = true;
1818 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301819 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001820 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1822 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001823 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301824 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001825 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1827 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001828 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301829 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830 }
1831
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001832 if(!is_meta_data_params) {
1833 ALOGV("%s: Not gapless meta data params", __func__);
1834 return 0;
1835 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836 out->send_new_metadata = 1;
1837 ALOGV("%s new encoder delay %u and padding %u", __func__,
1838 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1839
1840 return 0;
1841}
1842
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001843static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1844{
1845 return out == adev->primary_output || out == adev->voice_tx_output;
1846}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1849{
1850 struct stream_out *out = (struct stream_out *)stream;
1851 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001852 struct audio_usecase *usecase;
1853 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 struct str_parms *parms;
1855 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001856 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001857 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858
sangwoobc677242013-08-08 16:53:43 +09001859 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001860 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301862 if (!parms)
1863 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001864 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1865 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001868 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301871 * When HDMI cable is unplugged/usb hs is disconnected the
1872 * music playback is paused and the policy manager sends routing=0
1873 * But the audioflingercontinues to write data until standby time
1874 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875 * Avoid this by routing audio to speaker until standby.
1876 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301877 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1878 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001880 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1881 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001882 }
1883
1884 /*
1885 * select_devices() call below switches all the usecases on the same
1886 * backend to the new device. Refer to check_usecases_codec_backend() in
1887 * the select_devices(). But how do we undo this?
1888 *
1889 * For example, music playback is active on headset (deep-buffer usecase)
1890 * and if we go to ringtones and select a ringtone, low-latency usecase
1891 * will be started on headset+speaker. As we can't enable headset+speaker
1892 * and headset devices at the same time, select_devices() switches the music
1893 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1894 * So when the ringtone playback is completed, how do we undo the same?
1895 *
1896 * We are relying on the out_set_parameters() call on deep-buffer output,
1897 * once the ringtone playback is ended.
1898 * NOTE: We should not check if the current devices are same as new devices.
1899 * Because select_devices() must be called to switch back the music
1900 * playback to headset.
1901 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001902 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 out->devices = val;
1904
1905 if (!out->standby)
1906 select_devices(adev, out->usecase);
1907
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001908 if (output_drives_call(adev, out)) {
1909 if(!voice_is_in_call(adev)) {
1910 if (adev->mode == AUDIO_MODE_IN_CALL) {
1911 adev->current_call_output = out;
1912 ret = voice_start_call(adev);
1913 }
1914 } else {
1915 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001916 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001917 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001918 }
1919 }
1920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001922 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001924
1925 if (out == adev->primary_output) {
1926 pthread_mutex_lock(&adev->lock);
1927 audio_extn_set_parameters(adev, parms);
1928 pthread_mutex_unlock(&adev->lock);
1929 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001930 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001931 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001932 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001933
1934 audio_extn_dts_create_state_notifier_node(out->usecase);
1935 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1936 popcount(out->channel_mask),
1937 out->playback_started);
1938
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001939 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001940 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301943error:
Eric Laurent994a6932013-07-17 11:51:42 -07001944 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945 return ret;
1946}
1947
1948static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1949{
1950 struct stream_out *out = (struct stream_out *)stream;
1951 struct str_parms *query = str_parms_create_str(keys);
1952 char *str;
1953 char value[256];
1954 struct str_parms *reply = str_parms_create();
1955 size_t i, j;
1956 int ret;
1957 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001958
1959 if (!query || !reply) {
1960 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1961 return NULL;
1962 }
1963
Eric Laurent994a6932013-07-17 11:51:42 -07001964 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1966 if (ret >= 0) {
1967 value[0] = '\0';
1968 i = 0;
1969 while (out->supported_channel_masks[i] != 0) {
1970 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1971 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1972 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001973 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001975 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 first = false;
1977 break;
1978 }
1979 }
1980 i++;
1981 }
1982 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1983 str = str_parms_to_str(reply);
1984 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001985 voice_extn_out_get_parameters(out, query, reply);
1986 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001987 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001988 free(str);
1989 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001990 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001992
1993 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1994 if (ret >= 0) {
1995 value[0] = '\0';
1996 i = 0;
1997 first = true;
1998 while (out->supported_formats[i] != 0) {
1999 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2000 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2001 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002002 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002003 }
2004 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2005 first = false;
2006 break;
2007 }
2008 }
2009 i++;
2010 }
2011 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2012 str = str_parms_to_str(reply);
2013 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 str_parms_destroy(query);
2015 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002016 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 return str;
2018}
2019
2020static uint32_t out_get_latency(const struct audio_stream_out *stream)
2021{
2022 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002023 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Alexy Josephaa54c872014-12-03 02:46:47 -08002025 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002026 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002027 } else {
2028 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002030 }
2031
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302032 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002033 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034}
2035
2036static int out_set_volume(struct audio_stream_out *stream, float left,
2037 float right)
2038{
Eric Laurenta9024de2013-04-04 09:19:12 -07002039 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002040 int volume[2];
2041
Eric Laurenta9024de2013-04-04 09:19:12 -07002042 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2043 /* only take left channel into account: the API is for stereo anyway */
2044 out->muted = (left == 0.0f);
2045 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002046 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002047 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2048 /*
2049 * Set mute or umute on HDMI passthrough stream.
2050 * Only take left channel into account.
2051 * Mute is 0 and unmute 1
2052 */
2053 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2054 } else {
2055 char mixer_ctl_name[128];
2056 struct audio_device *adev = out->dev;
2057 struct mixer_ctl *ctl;
2058 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002059 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002061 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2062 "Compress Playback %d Volume", pcm_device_id);
2063 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2064 if (!ctl) {
2065 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2066 __func__, mixer_ctl_name);
2067 return -EINVAL;
2068 }
2069 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2070 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2071 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2072 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002073 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002074 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 return -ENOSYS;
2077}
2078
2079static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2080 size_t bytes)
2081{
2082 struct stream_out *out = (struct stream_out *)stream;
2083 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302084 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002085 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302088
Naresh Tanniru80659832014-06-04 18:17:56 +05302089 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002090 // increase written size during SSR to avoid mismatch
2091 // with the written frames count in AF
2092 if (!is_offload_usecase(out->usecase))
2093 out->written += bytes / (out->config.channels * sizeof(short));
2094
Naresh Tanniru80659832014-06-04 18:17:56 +05302095 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302096 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302097 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302098 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002099 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302100 //during SSR for compress usecase we should return error to flinger
2101 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2102 pthread_mutex_unlock(&out->lock);
2103 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302104 }
2105 }
2106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002108 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002109 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002110 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2111 ret = voice_extn_compress_voip_start_output_stream(out);
2112 else
2113 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002114 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002117 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 goto exit;
2119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002122 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002123 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002125 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2127 out->send_new_metadata = 0;
2128 }
2129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302131 if (ret < 0)
2132 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002133 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002134 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302135 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302137 } else if (-ENETRESET == ret) {
2138 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2139 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2140 pthread_mutex_unlock(&out->lock);
2141 out_standby(&out->stream.common);
2142 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002143 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302144 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002146 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002147 out->playback_started = 1;
2148 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002149
2150 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2151 popcount(out->channel_mask),
2152 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 }
2154 pthread_mutex_unlock(&out->lock);
2155 return ret;
2156 } else {
2157 if (out->pcm) {
2158 if (out->muted)
2159 memset((void *)buffer, 0, bytes);
2160 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002161 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2162 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2163 else
2164 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302165 if (ret < 0)
2166 ret = -errno;
2167 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002168 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 }
2171
2172exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302173 /* ToDo: There may be a corner case when SSR happens back to back during
2174 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302175 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302176 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302177 }
2178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 pthread_mutex_unlock(&out->lock);
2180
2181 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002182 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002183 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302184 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302185 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302186 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302187 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302188 out->standby = true;
2189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002191 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302192 out_get_sample_rate(&out->stream.common));
2193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 }
2195 return bytes;
2196}
2197
2198static int out_get_render_position(const struct audio_stream_out *stream,
2199 uint32_t *dsp_frames)
2200{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302202 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002203
2204 if (dsp_frames == NULL)
2205 return -EINVAL;
2206
2207 *dsp_frames = 0;
2208 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002209 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 pthread_mutex_lock(&out->lock);
2211 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302212 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302214 if (ret < 0)
2215 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002216 ALOGVV("%s rendered frames %d sample_rate %d",
2217 __func__, *dsp_frames, out->sample_rate);
2218 }
2219 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 if (-ENETRESET == ret) {
2221 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2222 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2223 return -EINVAL;
2224 } else if(ret < 0) {
2225 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2226 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302227 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2228 /*
2229 * Handle corner case where compress session is closed during SSR
2230 * and timestamp is queried
2231 */
2232 ALOGE(" ERROR: sound card not active, return error");
2233 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302234 } else {
2235 return 0;
2236 }
Zhou Song32a556e2015-05-05 10:46:56 +08002237 } else if (audio_is_linear_pcm(out->format)) {
2238 *dsp_frames = out->written;
2239 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 } else
2241 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242}
2243
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002244static int out_add_audio_effect(const struct audio_stream *stream __unused,
2245 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246{
2247 return 0;
2248}
2249
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002250static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2251 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252{
2253 return 0;
2254}
2255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002256static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2257 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258{
2259 return -EINVAL;
2260}
2261
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002262static int out_get_presentation_position(const struct audio_stream_out *stream,
2263 uint64_t *frames, struct timespec *timestamp)
2264{
2265 struct stream_out *out = (struct stream_out *)stream;
2266 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002267 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002268
2269 pthread_mutex_lock(&out->lock);
2270
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002271 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002272 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302273 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002274 &out->sample_rate);
2275 ALOGVV("%s rendered frames %ld sample_rate %d",
2276 __func__, dsp_frames, out->sample_rate);
2277 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302278 if (ret < 0)
2279 ret = -errno;
2280 if (-ENETRESET == ret) {
2281 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2282 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2283 ret = -EINVAL;
2284 } else
2285 ret = 0;
2286
Eric Laurent949a0892013-09-20 09:20:13 -07002287 /* this is the best we can do */
2288 clock_gettime(CLOCK_MONOTONIC, timestamp);
2289 }
2290 } else {
2291 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002292 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002293 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2294 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002295 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002296 // This adjustment accounts for buffering after app processor.
2297 // It is based on estimated DSP latency per use case, rather than exact.
2298 signed_frames -=
2299 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2300
Eric Laurent949a0892013-09-20 09:20:13 -07002301 // It would be unusual for this value to be negative, but check just in case ...
2302 if (signed_frames >= 0) {
2303 *frames = signed_frames;
2304 ret = 0;
2305 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002306 }
2307 }
2308 }
2309
2310 pthread_mutex_unlock(&out->lock);
2311
2312 return ret;
2313}
2314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315static int out_set_callback(struct audio_stream_out *stream,
2316 stream_callback_t callback, void *cookie)
2317{
2318 struct stream_out *out = (struct stream_out *)stream;
2319
2320 ALOGV("%s", __func__);
2321 pthread_mutex_lock(&out->lock);
2322 out->offload_callback = callback;
2323 out->offload_cookie = cookie;
2324 pthread_mutex_unlock(&out->lock);
2325 return 0;
2326}
2327
2328static int out_pause(struct audio_stream_out* stream)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
2331 int status = -ENOSYS;
2332 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002333 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002334 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002335 pthread_mutex_lock(&out->lock);
2336 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302337 struct audio_device *adev = out->dev;
2338 int snd_scard_state = get_snd_card_state(adev);
2339
2340 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2341 status = compress_pause(out->compr);
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002344
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302345 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002346 audio_extn_dts_notify_playback_state(out->usecase, 0,
2347 out->sample_rate, popcount(out->channel_mask),
2348 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002349 }
2350 pthread_mutex_unlock(&out->lock);
2351 }
2352 return status;
2353}
2354
2355static int out_resume(struct audio_stream_out* stream)
2356{
2357 struct stream_out *out = (struct stream_out *)stream;
2358 int status = -ENOSYS;
2359 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002360 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002361 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 status = 0;
2363 pthread_mutex_lock(&out->lock);
2364 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302365 struct audio_device *adev = out->dev;
2366 int snd_scard_state = get_snd_card_state(adev);
2367
2368 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2369 status = compress_resume(out->compr);
2370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002372
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302373 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002374 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2375 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 }
2377 pthread_mutex_unlock(&out->lock);
2378 }
2379 return status;
2380}
2381
2382static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2383{
2384 struct stream_out *out = (struct stream_out *)stream;
2385 int status = -ENOSYS;
2386 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002387 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 pthread_mutex_lock(&out->lock);
2389 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2390 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2391 else
2392 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2393 pthread_mutex_unlock(&out->lock);
2394 }
2395 return status;
2396}
2397
2398static int out_flush(struct audio_stream_out* stream)
2399{
2400 struct stream_out *out = (struct stream_out *)stream;
2401 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002402 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002403 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 pthread_mutex_lock(&out->lock);
2405 stop_compressed_output_l(out);
2406 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002407 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 return 0;
2409 }
2410 return -ENOSYS;
2411}
2412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413/** audio_stream_in implementation **/
2414static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2415{
2416 struct stream_in *in = (struct stream_in *)stream;
2417
2418 return in->config.rate;
2419}
2420
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002421static int in_set_sample_rate(struct audio_stream *stream __unused,
2422 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423{
2424 return -ENOSYS;
2425}
2426
2427static size_t in_get_buffer_size(const struct audio_stream *stream)
2428{
2429 struct stream_in *in = (struct stream_in *)stream;
2430
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002431 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2432 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002433 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2434 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002435
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002436 return in->config.period_size *
2437 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438}
2439
2440static uint32_t in_get_channels(const struct audio_stream *stream)
2441{
2442 struct stream_in *in = (struct stream_in *)stream;
2443
2444 return in->channel_mask;
2445}
2446
2447static audio_format_t in_get_format(const struct audio_stream *stream)
2448{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002449 struct stream_in *in = (struct stream_in *)stream;
2450
2451 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452}
2453
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002454static int in_set_format(struct audio_stream *stream __unused,
2455 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456{
2457 return -ENOSYS;
2458}
2459
2460static int in_standby(struct audio_stream *stream)
2461{
2462 struct stream_in *in = (struct stream_in *)stream;
2463 struct audio_device *adev = in->dev;
2464 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302465 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2466 stream, in->usecase, use_case_table[in->usecase]);
2467
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002468 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2469 /* Ignore standby in case of voip call because the voip input
2470 * stream is closed in adev_close_input_stream()
2471 */
2472 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2473 return status;
2474 }
2475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002477 if (!in->standby && in->is_st_session) {
2478 ALOGD("%s: sound trigger pcm stop lab", __func__);
2479 audio_extn_sound_trigger_stop_lab(in);
2480 in->standby = 1;
2481 }
2482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002484 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002486 if (in->pcm) {
2487 pcm_close(in->pcm);
2488 in->pcm = NULL;
2489 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002491 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 }
2493 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002494 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 return status;
2496}
2497
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002498static int in_dump(const struct audio_stream *stream __unused,
2499 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500{
2501 return 0;
2502}
2503
2504static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2505{
2506 struct stream_in *in = (struct stream_in *)stream;
2507 struct audio_device *adev = in->dev;
2508 struct str_parms *parms;
2509 char *str;
2510 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002511 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302513 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 parms = str_parms_create_str(kvpairs);
2515
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302516 if (!parms)
2517 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002520
2521 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2522 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 val = atoi(value);
2524 /* no audio source uses val == 0 */
2525 if ((in->source != val) && (val != 0)) {
2526 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002527 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2528 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2529 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2530 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002531 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002532 err = voice_extn_compress_voip_open_input_stream(in);
2533 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002534 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002535 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002536 }
2537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 }
2539 }
2540
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002541 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2542 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002544 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 in->device = val;
2546 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002547 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002548 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 }
2550 }
2551
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002552done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002554 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555
2556 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302557error:
Eric Laurent994a6932013-07-17 11:51:42 -07002558 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 return ret;
2560}
2561
2562static char* in_get_parameters(const struct audio_stream *stream,
2563 const char *keys)
2564{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002565 struct stream_in *in = (struct stream_in *)stream;
2566 struct str_parms *query = str_parms_create_str(keys);
2567 char *str;
2568 char value[256];
2569 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002570
2571 if (!query || !reply) {
2572 ALOGE("in_get_parameters: failed to create query or reply");
2573 return NULL;
2574 }
2575
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002576 ALOGV("%s: enter: keys - %s", __func__, keys);
2577
2578 voice_extn_in_get_parameters(in, query, reply);
2579
2580 str = str_parms_to_str(reply);
2581 str_parms_destroy(query);
2582 str_parms_destroy(reply);
2583
2584 ALOGV("%s: exit: returns - %s", __func__, str);
2585 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586}
2587
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002588static int in_set_gain(struct audio_stream_in *stream __unused,
2589 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590{
2591 return 0;
2592}
2593
2594static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2595 size_t bytes)
2596{
2597 struct stream_in *in = (struct stream_in *)stream;
2598 struct audio_device *adev = in->dev;
2599 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302600 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302603
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002604 if (in->is_st_session) {
2605 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2606 /* Read from sound trigger HAL */
2607 audio_extn_sound_trigger_read(in, buffer, bytes);
2608 pthread_mutex_unlock(&in->lock);
2609 return bytes;
2610 }
2611
2612 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2613 ALOGD(" %s: sound card is not active/SSR state", __func__);
2614 ret= -EIO;;
2615 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302616 }
2617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002619 pthread_mutex_lock(&adev->lock);
2620 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2621 ret = voice_extn_compress_voip_start_input_stream(in);
2622 else
2623 ret = start_input_stream(in);
2624 pthread_mutex_unlock(&adev->lock);
2625 if (ret != 0) {
2626 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 }
2628 in->standby = 0;
2629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630
2631 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002632 if (audio_extn_ssr_get_enabled() &&
2633 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002634 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002635 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2636 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002637 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2638 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002639 else
2640 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302641 if (ret < 0)
2642 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 }
2644
2645 /*
2646 * Instead of writing zeroes here, we could trust the hardware
2647 * to always provide zeroes when muted.
2648 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302649 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2650 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 memset(buffer, 0, bytes);
2652
2653exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302654 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302655 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002656 if (-ENETRESET == ret)
2657 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 pthread_mutex_unlock(&in->lock);
2660
2661 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302662 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302663 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302664 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302665 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302666 in->standby = true;
2667 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302668 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002670 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002671 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302672 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 }
2674 return bytes;
2675}
2676
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002677static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678{
2679 return 0;
2680}
2681
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002682static int add_remove_audio_effect(const struct audio_stream *stream,
2683 effect_handle_t effect,
2684 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002686 struct stream_in *in = (struct stream_in *)stream;
2687 int status = 0;
2688 effect_descriptor_t desc;
2689
2690 status = (*effect)->get_descriptor(effect, &desc);
2691 if (status != 0)
2692 return status;
2693
2694 pthread_mutex_lock(&in->lock);
2695 pthread_mutex_lock(&in->dev->lock);
2696 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2697 in->enable_aec != enable &&
2698 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2699 in->enable_aec = enable;
2700 if (!in->standby)
2701 select_devices(in->dev, in->usecase);
2702 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002703 if (in->enable_ns != enable &&
2704 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2705 in->enable_ns = enable;
2706 if (!in->standby)
2707 select_devices(in->dev, in->usecase);
2708 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002709 pthread_mutex_unlock(&in->dev->lock);
2710 pthread_mutex_unlock(&in->lock);
2711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 return 0;
2713}
2714
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002715static int in_add_audio_effect(const struct audio_stream *stream,
2716 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717{
Eric Laurent994a6932013-07-17 11:51:42 -07002718 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002719 return add_remove_audio_effect(stream, effect, true);
2720}
2721
2722static int in_remove_audio_effect(const struct audio_stream *stream,
2723 effect_handle_t effect)
2724{
Eric Laurent994a6932013-07-17 11:51:42 -07002725 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002726 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727}
2728
2729static int adev_open_output_stream(struct audio_hw_device *dev,
2730 audio_io_handle_t handle,
2731 audio_devices_t devices,
2732 audio_output_flags_t flags,
2733 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002734 struct audio_stream_out **stream_out,
2735 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736{
2737 struct audio_device *adev = (struct audio_device *)dev;
2738 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002739 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002740 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302743
2744 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2745 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2746 ALOGE(" sound card is not active rejecting compress output open request");
2747 return -EINVAL;
2748 }
2749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2751
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302752 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2753 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2754 devices, flags, &out->stream);
2755
2756
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002757 if (!out) {
2758 return -ENOMEM;
2759 }
2760
Haynes Mathew George204045b2015-02-25 20:32:03 -08002761 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2762 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 if (devices == AUDIO_DEVICE_NONE)
2765 devices = AUDIO_DEVICE_OUT_SPEAKER;
2766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 out->flags = flags;
2768 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002769 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002770 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 out->sample_rate = config->sample_rate;
2772 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2773 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002774 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002775 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002776 out->non_blocking = 0;
2777 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778
2779 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002780 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2781 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002782 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2783 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2784
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002785 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002786 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2787 ret = read_hdmi_channel_masks(out);
2788
2789 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2790 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002791 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002792 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002793 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002794
2795 if (config->sample_rate == 0)
2796 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2797 if (config->channel_mask == 0)
2798 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2799
2800 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2803 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002805 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002807 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2808 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002809 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002810 ret = voice_extn_compress_voip_open_output_stream(out);
2811 if (ret != 0) {
2812 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2813 __func__, ret);
2814 goto error_open;
2815 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2817 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2818 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2819 ALOGE("%s: Unsupported Offload information", __func__);
2820 ret = -EINVAL;
2821 goto error_open;
2822 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002823
2824 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2825 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2826 ALOGV("read and update_pass through formats");
2827 ret = audio_extn_dolby_update_passt_formats(adev, out);
2828 if(ret != 0) {
2829 goto error_open;
2830 }
2831 if(config->offload_info.format == 0)
2832 config->offload_info.format = out->supported_formats[0];
2833 }
2834
Mingming Yin90310102013-11-13 16:57:00 -08002835 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002836 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837 ALOGE("%s: Unsupported audio format", __func__);
2838 ret = -EINVAL;
2839 goto error_open;
2840 }
2841
2842 out->compr_config.codec = (struct snd_codec *)
2843 calloc(1, sizeof(struct snd_codec));
2844
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002845 if (!out->compr_config.codec) {
2846 ret = -ENOMEM;
2847 goto error_open;
2848 }
2849
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002850 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851 if (config->offload_info.channel_mask)
2852 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002853 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002855 config->offload_info.channel_mask = config->channel_mask;
2856 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002857 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858 out->sample_rate = config->offload_info.sample_rate;
2859
2860 out->stream.set_callback = out_set_callback;
2861 out->stream.pause = out_pause;
2862 out->stream.resume = out_resume;
2863 out->stream.drain = out_drain;
2864 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002865 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002867 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002868 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002869 audio_extn_dolby_get_snd_codec_id(adev, out,
2870 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002871 else
2872 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002874 if (audio_is_offload_pcm(config->offload_info.format)) {
2875 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002876 platform_get_pcm_offload_buffer_size(&config->offload_info);
2877 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2878 out->compr_config.fragment_size =
2879 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002880 } else {
2881 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002882 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002883 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2885 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302886 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 out->compr_config.codec->bit_rate =
2888 config->offload_info.bit_rate;
2889 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002890 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002892 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002893 /*TODO: Do we need to change it for passthrough */
2894 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895
Mingming Yin3ee55c62014-08-04 14:23:35 -07002896 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2897 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002898 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2899 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002900 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002901 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2902
Mingming Yin3ee55c62014-08-04 14:23:35 -07002903 if (out->bit_width == 24) {
2904 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2905 }
2906
Amit Shekhar6f461b12014-08-01 14:52:58 -07002907 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002908 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002909
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2911 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002912
Alexy Josephaa54c872014-12-03 02:46:47 -08002913 if (config->offload_info.use_small_bufs) {
2914 //this flag is set from framework only if its for PCM formats
2915 //no need to check for PCM format again
2916 out->non_blocking = 0;
2917 out->use_small_bufs = true;
2918 ALOGI("Keep write blocking for small buff: non_blockling %d",
2919 out->non_blocking);
2920 }
2921
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002922 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002923 out->offload_state = OFFLOAD_STATE_IDLE;
2924 out->playback_started = 0;
2925
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002926 audio_extn_dts_create_state_notifier_node(out->usecase);
2927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928 create_offload_callback_thread(out);
2929 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2930 __func__, config->offload_info.version,
2931 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002932 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002933 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002934 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2935 ret = voice_check_and_set_incall_music_usecase(adev, out);
2936 if (ret != 0) {
2937 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2938 __func__, ret);
2939 goto error_open;
2940 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002941 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2942 if (config->sample_rate == 0)
2943 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2944 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2945 config->sample_rate != 8000) {
2946 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2947 ret = -EINVAL;
2948 goto error_open;
2949 }
2950 out->sample_rate = config->sample_rate;
2951 out->config.rate = config->sample_rate;
2952 if (config->format == AUDIO_FORMAT_DEFAULT)
2953 config->format = AUDIO_FORMAT_PCM_16_BIT;
2954 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2955 config->format = AUDIO_FORMAT_PCM_16_BIT;
2956 ret = -EINVAL;
2957 goto error_open;
2958 }
2959 out->format = config->format;
2960 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2961 out->config = pcm_config_afe_proxy_playback;
2962 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002963 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002964 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2966 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002968 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2969 format = AUDIO_FORMAT_PCM_16_BIT;
2970 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2971 out->config = pcm_config_deep_buffer;
2972 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002973 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002974 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002975 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002976 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002977 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002978 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 }
2980
Amit Shekhar1d896042014-10-03 13:16:09 -07002981 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2982 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002983 /* TODO remove this hardcoding and check why width is zero*/
2984 if (out->bit_width == 0)
2985 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002986 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2987 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002988 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05302989 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002990 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2991 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2992 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002993 if(adev->primary_output == NULL)
2994 adev->primary_output = out;
2995 else {
2996 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002997 ret = -EEXIST;
2998 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002999 }
3000 }
3001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 /* Check if this usecase is already existing */
3003 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003004 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3005 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003008 ret = -EEXIST;
3009 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 }
3011 pthread_mutex_unlock(&adev->lock);
3012
3013 out->stream.common.get_sample_rate = out_get_sample_rate;
3014 out->stream.common.set_sample_rate = out_set_sample_rate;
3015 out->stream.common.get_buffer_size = out_get_buffer_size;
3016 out->stream.common.get_channels = out_get_channels;
3017 out->stream.common.get_format = out_get_format;
3018 out->stream.common.set_format = out_set_format;
3019 out->stream.common.standby = out_standby;
3020 out->stream.common.dump = out_dump;
3021 out->stream.common.set_parameters = out_set_parameters;
3022 out->stream.common.get_parameters = out_get_parameters;
3023 out->stream.common.add_audio_effect = out_add_audio_effect;
3024 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3025 out->stream.get_latency = out_get_latency;
3026 out->stream.set_volume = out_set_volume;
3027 out->stream.write = out_write;
3028 out->stream.get_render_position = out_get_render_position;
3029 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003030 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003033 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003034 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035
3036 config->format = out->stream.common.get_format(&out->stream.common);
3037 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3038 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3039
3040 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303041 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3042 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003043
3044 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3045 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3046 popcount(out->channel_mask), out->playback_started);
3047
Eric Laurent994a6932013-07-17 11:51:42 -07003048 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003050
3051error_open:
3052 free(out);
3053 *stream_out = NULL;
3054 ALOGD("%s: exit: ret %d", __func__, ret);
3055 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056}
3057
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003058static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 struct audio_stream_out *stream)
3060{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003061 struct stream_out *out = (struct stream_out *)stream;
3062 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003063 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303065 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3066
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003067 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303068 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003069 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303070 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003071 if(ret != 0)
3072 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3073 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003074 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 out_standby(&stream->common);
3076
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003077 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003078 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003080 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081 if (out->compr_config.codec != NULL)
3082 free(out->compr_config.codec);
3083 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003084
3085 if (adev->voice_tx_output == out)
3086 adev->voice_tx_output = NULL;
3087
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 pthread_cond_destroy(&out->cond);
3089 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003091 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092}
3093
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003094static void close_compress_sessions(struct audio_device *adev)
3095{
Mingming Yin7b762e72015-03-04 13:47:32 -08003096 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303097 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003098 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003099 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303100
3101 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003102 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303103 if (is_offload_usecase(usecase->id)) {
3104 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003105 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3106 out = usecase->stream.out;
3107 pthread_mutex_unlock(&adev->lock);
3108 out_standby(&out->stream.common);
3109 pthread_mutex_lock(&adev->lock);
3110 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303111 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003112 }
3113 pthread_mutex_unlock(&adev->lock);
3114}
3115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3117{
3118 struct audio_device *adev = (struct audio_device *)dev;
3119 struct str_parms *parms;
3120 char *str;
3121 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003122 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003123 int ret;
3124 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003126 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303129 if (!parms)
3130 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003131 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3132 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303133 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303134 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303135 struct listnode *node;
3136 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303137 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303138 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003139 //close compress sessions on OFFLINE status
3140 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303141 } else if (strstr(snd_card_status, "ONLINE")) {
3142 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303143 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303144 if (!platform_is_acdb_initialized(adev->platform)) {
3145 ret = platform_acdb_init(adev->platform);
3146 if(ret)
3147 ALOGE("acdb initialization is failed");
3148
3149 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303150 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 }
3152
3153 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003154 status = voice_set_parameters(adev, parms);
3155 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003156 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003158 status = platform_set_parameters(adev->platform, parms);
3159 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003160 goto done;
3161
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003162 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3163 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003164 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3166 adev->bluetooth_nrec = true;
3167 else
3168 adev->bluetooth_nrec = false;
3169 }
3170
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3172 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3174 adev->screen_off = false;
3175 else
3176 adev->screen_off = true;
3177 }
3178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 ret = str_parms_get_int(parms, "rotation", &val);
3180 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003181 bool reverse_speakers = false;
3182 switch(val) {
3183 // FIXME: note that the code below assumes that the speakers are in the correct placement
3184 // relative to the user when the device is rotated 90deg from its default rotation. This
3185 // assumption is device-specific, not platform-specific like this code.
3186 case 270:
3187 reverse_speakers = true;
3188 break;
3189 case 0:
3190 case 90:
3191 case 180:
3192 break;
3193 default:
3194 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003195 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003196 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003197 if (status == 0) {
3198 if (adev->speaker_lr_swap != reverse_speakers) {
3199 adev->speaker_lr_swap = reverse_speakers;
3200 // only update the selected device if there is active pcm playback
3201 struct audio_usecase *usecase;
3202 struct listnode *node;
3203 list_for_each(node, &adev->usecase_list) {
3204 usecase = node_to_item(node, struct audio_usecase, list);
3205 if (usecase->type == PCM_PLAYBACK) {
3206 select_devices(adev, usecase->id);
3207 break;
3208 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003209 }
3210 }
3211 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003212 }
3213
Mingming Yin514a8bc2014-07-29 15:22:21 -07003214 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3215 if (ret >= 0) {
3216 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3217 adev->bt_wb_speech_enabled = true;
3218 else
3219 adev->bt_wb_speech_enabled = false;
3220 }
3221
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003222 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3223 if (ret >= 0) {
3224 val = atoi(value);
3225 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3226 ALOGV("cache new edid");
3227 platform_cache_edid(adev->platform);
3228 }
3229 }
3230
3231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3232 if (ret >= 0) {
3233 val = atoi(value);
3234 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3235 ALOGV("invalidate cached edid");
3236 platform_invalidate_edid(adev->platform);
3237 }
3238 }
3239
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003240 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003241
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003242done:
3243 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003244 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303245error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003246 ALOGV("%s: exit with code(%d)", __func__, status);
3247 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248}
3249
3250static char* adev_get_parameters(const struct audio_hw_device *dev,
3251 const char *keys)
3252{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003253 struct audio_device *adev = (struct audio_device *)dev;
3254 struct str_parms *reply = str_parms_create();
3255 struct str_parms *query = str_parms_create_str(keys);
3256 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303257 char value[256] = {0};
3258 int ret = 0;
3259
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003260 if (!query || !reply) {
3261 ALOGE("adev_get_parameters: failed to create query or reply");
3262 return NULL;
3263 }
3264
Naresh Tannirud7205b62014-06-20 02:54:48 +05303265 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3266 sizeof(value));
3267 if (ret >=0) {
3268 int val = 1;
3269 pthread_mutex_lock(&adev->snd_card_status.lock);
3270 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3271 val = 0;
3272 pthread_mutex_unlock(&adev->snd_card_status.lock);
3273 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3274 goto exit;
3275 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003276
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003277 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003278 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003279 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003280 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303281 pthread_mutex_unlock(&adev->lock);
3282
Naresh Tannirud7205b62014-06-20 02:54:48 +05303283exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003284 str = str_parms_to_str(reply);
3285 str_parms_destroy(query);
3286 str_parms_destroy(reply);
3287
3288 ALOGV("%s: exit: returns - %s", __func__, str);
3289 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290}
3291
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003292static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293{
3294 return 0;
3295}
3296
3297static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3298{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003299 int ret;
3300 struct audio_device *adev = (struct audio_device *)dev;
3301 pthread_mutex_lock(&adev->lock);
3302 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003303 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003304 pthread_mutex_unlock(&adev->lock);
3305 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3309 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return -ENOSYS;
3312}
3313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003314static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3315 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return -ENOSYS;
3318}
3319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003320static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3321 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return -ENOSYS;
3324}
3325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003326static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3327 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return -ENOSYS;
3330}
3331
3332static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3333{
3334 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 pthread_mutex_lock(&adev->lock);
3337 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003338 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003340 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3341 voice_is_in_call(adev)) {
3342 voice_stop_call(adev);
3343 adev->current_call_output = NULL;
3344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 }
3346 pthread_mutex_unlock(&adev->lock);
3347 return 0;
3348}
3349
3350static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3351{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003352 int ret;
3353
3354 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003355 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003356 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3357 pthread_mutex_unlock(&adev->lock);
3358
3359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360}
3361
3362static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3363{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003364 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 return 0;
3366}
3367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003368static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 const struct audio_config *config)
3370{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003371 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003373 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3374 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375}
3376
3377static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003378 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 audio_devices_t devices,
3380 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003381 struct audio_stream_in **stream_in,
3382 audio_input_flags_t flags __unused,
3383 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003384 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385{
3386 struct audio_device *adev = (struct audio_device *)dev;
3387 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003388 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003389 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003390 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 *stream_in = NULL;
3393 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3394 return -EINVAL;
3395
3396 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003397
3398 if (!in) {
3399 ALOGE("failed to allocate input stream");
3400 return -ENOMEM;
3401 }
3402
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303403 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003404 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3405 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003407 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 in->stream.common.get_sample_rate = in_get_sample_rate;
3410 in->stream.common.set_sample_rate = in_set_sample_rate;
3411 in->stream.common.get_buffer_size = in_get_buffer_size;
3412 in->stream.common.get_channels = in_get_channels;
3413 in->stream.common.get_format = in_get_format;
3414 in->stream.common.set_format = in_set_format;
3415 in->stream.common.standby = in_standby;
3416 in->stream.common.dump = in_dump;
3417 in->stream.common.set_parameters = in_set_parameters;
3418 in->stream.common.get_parameters = in_get_parameters;
3419 in->stream.common.add_audio_effect = in_add_audio_effect;
3420 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3421 in->stream.set_gain = in_set_gain;
3422 in->stream.read = in_read;
3423 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3424
3425 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003426 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 in->standby = 1;
3429 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003430 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431
3432 /* Update config params with the requested sample rate and channels */
3433 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003434 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3435 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3436 is_low_latency = true;
3437#if LOW_LATENCY_CAPTURE_USE_CASE
3438 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3439#endif
3440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003443 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003445 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303446 if (adev->mode != AUDIO_MODE_IN_CALL) {
3447 ret = -EINVAL;
3448 goto err_open;
3449 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003450 if (config->sample_rate == 0)
3451 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3452 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3453 config->sample_rate != 8000) {
3454 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3455 ret = -EINVAL;
3456 goto err_open;
3457 }
3458 if (config->format == AUDIO_FORMAT_DEFAULT)
3459 config->format = AUDIO_FORMAT_PCM_16_BIT;
3460 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3461 config->format = AUDIO_FORMAT_PCM_16_BIT;
3462 ret = -EINVAL;
3463 goto err_open;
3464 }
3465
3466 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3467 in->config = pcm_config_afe_proxy_record;
3468 in->config.channels = channel_count;
3469 in->config.rate = config->sample_rate;
3470 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003471 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003472 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003473 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3474 ret = -EINVAL;
3475 goto err_open;
3476 }
3477 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003478 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 }
Mingming Yine62d7842013-10-25 16:26:03 -07003480 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003481 audio_extn_compr_cap_format_supported(config->format) &&
3482 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003483 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003484 } else {
3485 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003486 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003487 buffer_size = get_input_buffer_size(config->sample_rate,
3488 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003489 channel_count,
3490 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003491 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003492 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3493 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3494 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3495 (in->config.rate == 8000 || in->config.rate == 16000) &&
3496 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3497 voice_extn_compress_voip_open_input_stream(in);
3498 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003499 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003501 /* This stream could be for sound trigger lab,
3502 get sound trigger pcm if present */
3503 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303504 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003507 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003508 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509
3510err_open:
3511 free(in);
3512 *stream_in = NULL;
3513 return ret;
3514}
3515
3516static void adev_close_input_stream(struct audio_hw_device *dev,
3517 struct audio_stream_in *stream)
3518{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003519 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003520 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003521 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303522
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303523 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003524
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303525 /* Disable echo reference while closing input stream */
3526 platform_set_echo_reference(adev->platform, false);
3527
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003528 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303529 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003530 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303531 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003532 if (ret != 0)
3533 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3534 __func__, ret);
3535 } else
3536 in_standby(&stream->common);
3537
Mingming Yin7b762e72015-03-04 13:47:32 -08003538 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003539 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003540 audio_extn_ssr_deinit();
3541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542
Mingming Yine62d7842013-10-25 16:26:03 -07003543 if(audio_extn_compr_cap_enabled() &&
3544 audio_extn_compr_cap_format_supported(in->config.format))
3545 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003546
3547 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 return;
3549}
3550
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003551static int adev_dump(const audio_hw_device_t *device __unused,
3552 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553{
3554 return 0;
3555}
3556
3557static int adev_close(hw_device_t *device)
3558{
3559 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003560
3561 if (!adev)
3562 return 0;
3563
3564 pthread_mutex_lock(&adev_init_lock);
3565
3566 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003567 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003568 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003569 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003570 audio_route_free(adev->audio_route);
3571 free(adev->snd_dev_ref_cnt);
3572 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003573 free(device);
3574 adev = NULL;
3575 }
3576 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577 return 0;
3578}
3579
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003580/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3581 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3582 * just that it _might_ work.
3583 */
3584static int period_size_is_plausible_for_low_latency(int period_size)
3585{
3586 switch (period_size) {
3587 case 160:
3588 case 240:
3589 case 320:
3590 case 480:
3591 return 1;
3592 default:
3593 return 0;
3594 }
3595}
3596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597static int adev_open(const hw_module_t *module, const char *name,
3598 hw_device_t **device)
3599{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003600 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003602 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3604
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003605 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003606 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003607 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003608 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003609 ALOGD("%s: returning existing instance of adev", __func__);
3610 ALOGD("%s: exit", __func__);
3611 pthread_mutex_unlock(&adev_init_lock);
3612 return 0;
3613 }
3614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 adev = calloc(1, sizeof(struct audio_device));
3616
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003617 if (!adev) {
3618 pthread_mutex_unlock(&adev_init_lock);
3619 return -ENOMEM;
3620 }
3621
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003622 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3625 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3626 adev->device.common.module = (struct hw_module_t *)module;
3627 adev->device.common.close = adev_close;
3628
3629 adev->device.init_check = adev_init_check;
3630 adev->device.set_voice_volume = adev_set_voice_volume;
3631 adev->device.set_master_volume = adev_set_master_volume;
3632 adev->device.get_master_volume = adev_get_master_volume;
3633 adev->device.set_master_mute = adev_set_master_mute;
3634 adev->device.get_master_mute = adev_get_master_mute;
3635 adev->device.set_mode = adev_set_mode;
3636 adev->device.set_mic_mute = adev_set_mic_mute;
3637 adev->device.get_mic_mute = adev_get_mic_mute;
3638 adev->device.set_parameters = adev_set_parameters;
3639 adev->device.get_parameters = adev_get_parameters;
3640 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3641 adev->device.open_output_stream = adev_open_output_stream;
3642 adev->device.close_output_stream = adev_close_output_stream;
3643 adev->device.open_input_stream = adev_open_input_stream;
3644 adev->device.close_input_stream = adev_close_input_stream;
3645 adev->device.dump = adev_dump;
3646
3647 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003649 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003650 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003653 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003654 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003655 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003656 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003657 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003658 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003659 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303660
3661 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3662 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003664 adev->platform = platform_init(adev);
3665 if (!adev->platform) {
3666 free(adev->snd_dev_ref_cnt);
3667 free(adev);
3668 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3669 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003670 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003671 return -EINVAL;
3672 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003673
Naresh Tanniru4c630392014-05-12 01:05:52 +05303674 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3675
Eric Laurentc4aef752013-09-12 17:45:53 -07003676 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3677 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3678 if (adev->visualizer_lib == NULL) {
3679 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3680 } else {
3681 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3682 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003683 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003684 "visualizer_hal_start_output");
3685 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003686 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003687 "visualizer_hal_stop_output");
3688 }
3689 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003690 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003691 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003692
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003693 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3694 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3695 if (adev->offload_effects_lib == NULL) {
3696 ALOGE("%s: DLOPEN failed for %s", __func__,
3697 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3698 } else {
3699 ALOGV("%s: DLOPEN successful for %s", __func__,
3700 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3701 adev->offload_effects_start_output =
3702 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3703 "offload_effects_bundle_hal_start_output");
3704 adev->offload_effects_stop_output =
3705 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3706 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003707 adev->offload_effects_set_hpx_state =
3708 (int (*)(bool))dlsym(adev->offload_effects_lib,
3709 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003710 }
3711 }
3712
Mingming Yin514a8bc2014-07-29 15:22:21 -07003713 adev->bt_wb_speech_enabled = false;
3714
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003715 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 *device = &adev->device.common;
3717
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003718 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3719 &adev->streams_output_cfg_list);
3720
Kiran Kandi910e1862013-10-29 13:29:42 -07003721 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003722
3723 char value[PROPERTY_VALUE_MAX];
3724 int trial;
3725 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3726 trial = atoi(value);
3727 if (period_size_is_plausible_for_low_latency(trial)) {
3728 pcm_config_low_latency.period_size = trial;
3729 pcm_config_low_latency.start_threshold = trial / 4;
3730 pcm_config_low_latency.avail_min = trial / 4;
3731 configured_low_latency_capture_period_size = trial;
3732 }
3733 }
3734 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3735 trial = atoi(value);
3736 if (period_size_is_plausible_for_low_latency(trial)) {
3737 configured_low_latency_capture_period_size = trial;
3738 }
3739 }
3740
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003741 pthread_mutex_unlock(&adev_init_lock);
3742
Eric Laurent994a6932013-07-17 11:51:42 -07003743 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 return 0;
3745}
3746
3747static struct hw_module_methods_t hal_module_methods = {
3748 .open = adev_open,
3749};
3750
3751struct audio_module HAL_MODULE_INFO_SYM = {
3752 .common = {
3753 .tag = HARDWARE_MODULE_TAG,
3754 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3755 .hal_api_version = HARDWARE_HAL_API_VERSION,
3756 .id = AUDIO_HARDWARE_MODULE_ID,
3757 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003758 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 .methods = &hal_module_methods,
3760 },
3761};