blob: b3812a8d7557a163de6ba434304490dc863615bd [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);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800423 strcpy(mixer_path, use_case_table[usecase->id]);
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;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800445 strcpy(mixer_path, use_case_table[usecase->id]);
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;
585
586 /*
587 * This function is to make sure that all the usecases that are active on
588 * the hardware codec backend are always routed to any one device that is
589 * handled by the hardware codec.
590 * For example, if low-latency and deep-buffer usecases are currently active
591 * on speaker and out_set_parameters(headset) is received on low-latency
592 * output, then we have to make sure deep-buffer is also switched to headset,
593 * because of the limitation that both the devices cannot be enabled
594 * at the same time as they share the same backend.
595 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700596 /*
597 * This call is to check if we need to force routing for a particular stream
598 * If there is a backend configuration change for the device when a
599 * new stream starts, then ADM needs to be closed and re-opened with the new
600 * configuraion. This call check if we need to re-route all the streams
601 * associated with the backend. Touch tone + 24 bit playback.
602 */
603 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605 /* Disable all the usecases on the shared backend other than the
606 specified usecase */
607 for (i = 0; i < AUDIO_USECASE_MAX; i++)
608 switch_device[i] = false;
609
610 list_for_each(node, &adev->usecase_list) {
611 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800612 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700614 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
616 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
617 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700618 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700619 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 switch_device[usecase->id] = true;
621 num_uc_to_switch++;
622 }
623 }
624
625 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700626 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700627
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530628 /* Make sure the previous devices to be disabled first and then enable the
629 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 list_for_each(node, &adev->usecase_list) {
631 usecase = node_to_item(node, struct audio_usecase, list);
632 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700633 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 }
635 }
636
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700637 list_for_each(node, &adev->usecase_list) {
638 usecase = node_to_item(node, struct audio_usecase, list);
639 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700640 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700641 }
642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644 /* Re-route all the usecases on the shared backend other than the
645 specified usecase to new snd devices */
646 list_for_each(node, &adev->usecase_list) {
647 usecase = node_to_item(node, struct audio_usecase, list);
648 /* Update the out_snd_device only before enabling the audio route */
649 if (switch_device[usecase->id] ) {
650 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800651 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530652 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700653 }
654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655 }
656}
657
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700658static void check_and_route_capture_usecases(struct audio_device *adev,
659 struct audio_usecase *uc_info,
660 snd_device_t snd_device)
661{
662 struct listnode *node;
663 struct audio_usecase *usecase;
664 bool switch_device[AUDIO_USECASE_MAX];
665 int i, num_uc_to_switch = 0;
666
667 /*
668 * This function is to make sure that all the active capture usecases
669 * are always routed to the same input sound device.
670 * For example, if audio-record and voice-call usecases are currently
671 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
672 * is received for voice call then we have to make sure that audio-record
673 * usecase is also switched to earpiece i.e. voice-dmic-ef,
674 * because of the limitation that two devices cannot be enabled
675 * at the same time if they share the same backend.
676 */
677 for (i = 0; i < AUDIO_USECASE_MAX; i++)
678 switch_device[i] = false;
679
680 list_for_each(node, &adev->usecase_list) {
681 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800682 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700683 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700684 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530685 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700686 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700687 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
688 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700689 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700690 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700691 switch_device[usecase->id] = true;
692 num_uc_to_switch++;
693 }
694 }
695
696 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700697 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700698
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530699 /* Make sure the previous devices to be disabled first and then enable the
700 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700701 list_for_each(node, &adev->usecase_list) {
702 usecase = node_to_item(node, struct audio_usecase, list);
703 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700704 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800705 }
706 }
707
708 list_for_each(node, &adev->usecase_list) {
709 usecase = node_to_item(node, struct audio_usecase, list);
710 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700712 }
713 }
714
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700715 /* Re-route all the usecases on the shared backend other than the
716 specified usecase to new snd devices */
717 list_for_each(node, &adev->usecase_list) {
718 usecase = node_to_item(node, struct audio_usecase, list);
719 /* Update the in_snd_device only before enabling the audio route */
720 if (switch_device[usecase->id] ) {
721 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800722 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530723 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 }
725 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700726 }
727}
728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800729/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700730static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800731{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700732 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700733 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800734
735 switch (channels) {
736 /*
737 * Do not handle stereo output in Multi-channel cases
738 * Stereo case is handled in normal playback path
739 */
740 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700741 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
742 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
743 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
744 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
745 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
746 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747 break;
748 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700749 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
750 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
751 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
752 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
753 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
754 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800756 break;
757 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700758 ALOGE("HDMI does not support multi channel playback");
759 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760 break;
761 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700762 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763}
764
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800765audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
766 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700767{
768 struct audio_usecase *usecase;
769 struct listnode *node;
770
771 list_for_each(node, &adev->usecase_list) {
772 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800773 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700774 ALOGV("%s: usecase id %d", __func__, usecase->id);
775 return usecase->id;
776 }
777 }
778 return USECASE_INVALID;
779}
780
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700781struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700782 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700783{
784 struct audio_usecase *usecase;
785 struct listnode *node;
786
787 list_for_each(node, &adev->usecase_list) {
788 usecase = node_to_item(node, struct audio_usecase, list);
789 if (usecase->id == uc_id)
790 return usecase;
791 }
792 return NULL;
793}
794
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700795int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800796{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800797 snd_device_t out_snd_device = SND_DEVICE_NONE;
798 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 struct audio_usecase *usecase = NULL;
800 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800801 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800802 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800803 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800804 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700807 usecase = get_usecase_from_list(adev, uc_id);
808 if (usecase == NULL) {
809 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
810 return -EINVAL;
811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800813 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800814 (usecase->type == VOIP_CALL) ||
815 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700816 out_snd_device = platform_get_output_snd_device(adev->platform,
817 usecase->stream.out->devices);
818 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 usecase->devices = usecase->stream.out->devices;
820 } else {
821 /*
822 * If the voice call is active, use the sound devices of voice call usecase
823 * so that it would not result any device switch. All the usecases will
824 * be switched to new device when select_devices() is called for voice call
825 * usecase. This is to avoid switching devices for voice call when
826 * check_usecases_codec_backend() is called below.
827 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700828 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700829 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800830 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700831 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
832 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 in_snd_device = vc_usecase->in_snd_device;
834 out_snd_device = vc_usecase->out_snd_device;
835 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800836 } else if (voice_extn_compress_voip_is_active(adev)) {
837 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700838 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530839 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700840 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800841 in_snd_device = voip_usecase->in_snd_device;
842 out_snd_device = voip_usecase->out_snd_device;
843 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800844 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800845 hfp_ucid = audio_extn_hfp_get_usecase();
846 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700847 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800848 in_snd_device = hfp_usecase->in_snd_device;
849 out_snd_device = hfp_usecase->out_snd_device;
850 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 }
852 if (usecase->type == PCM_PLAYBACK) {
853 usecase->devices = usecase->stream.out->devices;
854 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700855 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700856 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700858 if (usecase->stream.out == adev->primary_output &&
859 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800860 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
861 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700862 select_devices(adev, adev->active_input->usecase);
863 }
864 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 } else if (usecase->type == PCM_CAPTURE) {
866 usecase->devices = usecase->stream.in->device;
867 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700868 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700869 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530870 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
871 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
872 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
873 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700874 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800875 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700876 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
877 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700878 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700879 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 }
883
884 if (out_snd_device == usecase->out_snd_device &&
885 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800886 return 0;
887 }
888
sangwoobc677242013-08-08 16:53:43 +0900889 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700890 out_snd_device, platform_get_snd_device_name(out_snd_device),
891 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800893 /*
894 * Limitation: While in call, to do a device switch we need to disable
895 * and enable both RX and TX devices though one of them is same as current
896 * device.
897 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700898 if ((usecase->type == VOICE_CALL) &&
899 (usecase->in_snd_device != SND_DEVICE_NONE) &&
900 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700901 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800902 }
903
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 /* Disable current sound devices */
905 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700906 disable_audio_route(adev, usecase);
907 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 }
909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700911 disable_audio_route(adev, usecase);
912 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 }
914
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800915 /* Applicable only on the targets that has external modem.
916 * New device information should be sent to modem before enabling
917 * the devices to reduce in-call device switch time.
918 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700919 if ((usecase->type == VOICE_CALL) &&
920 (usecase->in_snd_device != SND_DEVICE_NONE) &&
921 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800922 status = platform_switch_voice_call_enable_device_config(adev->platform,
923 out_snd_device,
924 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700925 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 /* Enable new sound devices */
928 if (out_snd_device != SND_DEVICE_NONE) {
929 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
930 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700931 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932 }
933
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 if (in_snd_device != SND_DEVICE_NONE) {
935 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700936 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700937 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700938
Avinash Vaish71a8b972014-07-24 15:36:33 +0530939 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700940 status = platform_switch_voice_call_device_post(adev->platform,
941 out_snd_device,
942 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530943 enable_audio_route_for_voice_usecases(adev, usecase);
944 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800945
sangwoo170731f2013-06-08 15:36:36 +0900946 usecase->in_snd_device = in_snd_device;
947 usecase->out_snd_device = out_snd_device;
948
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530949 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700950 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530951 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700952 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530953 usecase->stream.out->flags,
954 usecase->stream.out->format,
955 usecase->stream.out->sample_rate,
956 usecase->stream.out->bit_width,
957 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700958 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530959 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700960
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700961 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900962
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800963 /* Applicable only on the targets that has external modem.
964 * Enable device command should be sent to modem only after
965 * enabling voice call mixer controls
966 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700967 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800968 status = platform_switch_voice_call_usecase_route_post(adev->platform,
969 out_snd_device,
970 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530971 ALOGD("%s: done",__func__);
972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 return status;
974}
975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976static int stop_input_stream(struct stream_in *in)
977{
978 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979 struct audio_usecase *uc_info;
980 struct audio_device *adev = in->dev;
981
Eric Laurentc8400632013-02-14 19:04:54 -0800982 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983
Eric Laurent994a6932013-07-17 11:51:42 -0700984 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986 uc_info = get_usecase_from_list(adev, in->usecase);
987 if (uc_info == NULL) {
988 ALOGE("%s: Could not find the usecase (%d) in the list",
989 __func__, in->usecase);
990 return -EINVAL;
991 }
992
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800993 /* Close in-call recording streams */
994 voice_check_and_stop_incall_rec_usecase(adev, in);
995
Eric Laurent150dbfe2013-02-27 14:31:02 -0800996 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700997 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998
999 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001000 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001002 list_remove(&uc_info->list);
1003 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004
Eric Laurent994a6932013-07-17 11:51:42 -07001005 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006 return ret;
1007}
1008
1009int start_input_stream(struct stream_in *in)
1010{
1011 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001012 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 struct audio_usecase *uc_info;
1014 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301015 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016
Mingming Yine62d7842013-10-25 16:26:03 -07001017 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301018 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1019 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001020
Naresh Tanniru80659832014-06-04 18:17:56 +05301021
1022 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301023 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301024 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301025 goto error_config;
1026 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301027
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001028 /* Check if source matches incall recording usecase criteria */
1029 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1030 if (ret)
1031 goto error_config;
1032 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001033 ALOGD("%s: Updated usecase(%d: %s)",
1034 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001035
Eric Laurentb23d5282013-05-14 15:27:20 -07001036 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037 if (in->pcm_device_id < 0) {
1038 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1039 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001040 ret = -EINVAL;
1041 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043
1044 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001046
1047 if (!uc_info) {
1048 ret = -ENOMEM;
1049 goto error_config;
1050 }
1051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052 uc_info->id = in->usecase;
1053 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001054 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001055 uc_info->devices = in->device;
1056 uc_info->in_snd_device = SND_DEVICE_NONE;
1057 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001059 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301060 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062
Eric Laurentc8400632013-02-14 19:04:54 -08001063 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001064 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1065
1066 unsigned int flags = PCM_IN;
1067 unsigned int pcm_open_retry_count = 0;
1068
1069 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1070 flags |= PCM_MMAP | PCM_NOIRQ;
1071 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1072 }
1073
1074 while (1) {
1075 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1076 flags, &in->config);
1077 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1078 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1079 if (in->pcm != NULL) {
1080 pcm_close(in->pcm);
1081 in->pcm = NULL;
1082 }
1083 if (pcm_open_retry_count-- == 0) {
1084 ret = -EIO;
1085 goto error_open;
1086 }
1087 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1088 continue;
1089 }
1090 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301092 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301093
Eric Laurent994a6932013-07-17 11:51:42 -07001094 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001095 return ret;
1096
1097error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301099 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001100
1101error_config:
1102 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001104
1105 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106}
1107
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001108/* must be called with out->lock locked */
1109static int send_offload_cmd_l(struct stream_out* out, int command)
1110{
1111 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1112
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001113 if (!cmd) {
1114 ALOGE("failed to allocate mem for command 0x%x", command);
1115 return -ENOMEM;
1116 }
1117
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001118 ALOGVV("%s %d", __func__, command);
1119
1120 cmd->cmd = command;
1121 list_add_tail(&out->offload_cmd_list, &cmd->node);
1122 pthread_cond_signal(&out->offload_cond);
1123 return 0;
1124}
1125
1126/* must be called iwth out->lock locked */
1127static void stop_compressed_output_l(struct stream_out *out)
1128{
1129 out->offload_state = OFFLOAD_STATE_IDLE;
1130 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001131 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001132 if (out->compr != NULL) {
1133 compress_stop(out->compr);
1134 while (out->offload_thread_blocked) {
1135 pthread_cond_wait(&out->cond, &out->lock);
1136 }
1137 }
1138}
1139
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001140bool is_offload_usecase(audio_usecase_t uc_id)
1141{
1142 unsigned int i;
1143 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1144 if (uc_id == offload_usecases[i])
1145 return true;
1146 }
1147 return false;
1148}
1149
1150static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1151{
1152 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1153 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1154 char value[PROPERTY_VALUE_MAX] = {0};
1155
1156 property_get("audio.offload.multiple.enabled", value, NULL);
1157 if (!(atoi(value) || !strncmp("true", value, 4)))
1158 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1159
1160 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1161 for (i = 0; i < num_usecase; i++) {
1162 if (!(adev->offload_usecases_state & (0x1<<i))) {
1163 adev->offload_usecases_state |= 0x1 << i;
1164 ret = offload_usecases[i];
1165 break;
1166 }
1167 }
1168 ALOGV("%s: offload usecase is %d", __func__, ret);
1169 return ret;
1170}
1171
1172static void free_offload_usecase(struct audio_device *adev,
1173 audio_usecase_t uc_id)
1174{
1175 unsigned int i;
1176 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1177 if (offload_usecases[i] == uc_id) {
1178 adev->offload_usecases_state &= ~(0x1<<i);
1179 break;
1180 }
1181 }
1182 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1183}
1184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001185static void *offload_thread_loop(void *context)
1186{
1187 struct stream_out *out = (struct stream_out *) context;
1188 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001189 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001190
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001191 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1192 set_sched_policy(0, SP_FOREGROUND);
1193 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1194
1195 ALOGV("%s", __func__);
1196 pthread_mutex_lock(&out->lock);
1197 for (;;) {
1198 struct offload_cmd *cmd = NULL;
1199 stream_callback_event_t event;
1200 bool send_callback = false;
1201
1202 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1203 __func__, list_empty(&out->offload_cmd_list),
1204 out->offload_state);
1205 if (list_empty(&out->offload_cmd_list)) {
1206 ALOGV("%s SLEEPING", __func__);
1207 pthread_cond_wait(&out->offload_cond, &out->lock);
1208 ALOGV("%s RUNNING", __func__);
1209 continue;
1210 }
1211
1212 item = list_head(&out->offload_cmd_list);
1213 cmd = node_to_item(item, struct offload_cmd, node);
1214 list_remove(item);
1215
1216 ALOGVV("%s STATE %d CMD %d out->compr %p",
1217 __func__, out->offload_state, cmd->cmd, out->compr);
1218
1219 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1220 free(cmd);
1221 break;
1222 }
1223
1224 if (out->compr == NULL) {
1225 ALOGE("%s: Compress handle is NULL", __func__);
1226 pthread_cond_signal(&out->cond);
1227 continue;
1228 }
1229 out->offload_thread_blocked = true;
1230 pthread_mutex_unlock(&out->lock);
1231 send_callback = false;
1232 switch(cmd->cmd) {
1233 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001234 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001235 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001236 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001237 send_callback = true;
1238 event = STREAM_CBK_EVENT_WRITE_READY;
1239 break;
1240 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001241 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301242 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001243 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301244 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001245 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301246 if (ret < 0)
1247 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301248 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301249 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001250 compress_drain(out->compr);
1251 else
1252 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301253 if (ret != -ENETRESET) {
1254 send_callback = true;
1255 event = STREAM_CBK_EVENT_DRAIN_READY;
1256 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1257 } else
1258 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001259 break;
1260 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001261 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001262 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001263 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001264 send_callback = true;
1265 event = STREAM_CBK_EVENT_DRAIN_READY;
1266 break;
1267 default:
1268 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1269 break;
1270 }
1271 pthread_mutex_lock(&out->lock);
1272 out->offload_thread_blocked = false;
1273 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001274 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001275 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001277 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001278 free(cmd);
1279 }
1280
1281 pthread_cond_signal(&out->cond);
1282 while (!list_empty(&out->offload_cmd_list)) {
1283 item = list_head(&out->offload_cmd_list);
1284 list_remove(item);
1285 free(node_to_item(item, struct offload_cmd, node));
1286 }
1287 pthread_mutex_unlock(&out->lock);
1288
1289 return NULL;
1290}
1291
1292static int create_offload_callback_thread(struct stream_out *out)
1293{
1294 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1295 list_init(&out->offload_cmd_list);
1296 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1297 offload_thread_loop, out);
1298 return 0;
1299}
1300
1301static int destroy_offload_callback_thread(struct stream_out *out)
1302{
1303 pthread_mutex_lock(&out->lock);
1304 stop_compressed_output_l(out);
1305 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1306
1307 pthread_mutex_unlock(&out->lock);
1308 pthread_join(out->offload_thread, (void **) NULL);
1309 pthread_cond_destroy(&out->offload_cond);
1310
1311 return 0;
1312}
1313
Eric Laurent07eeafd2013-10-06 12:52:49 -07001314static bool allow_hdmi_channel_config(struct audio_device *adev)
1315{
1316 struct listnode *node;
1317 struct audio_usecase *usecase;
1318 bool ret = true;
1319
1320 list_for_each(node, &adev->usecase_list) {
1321 usecase = node_to_item(node, struct audio_usecase, list);
1322 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1323 /*
1324 * If voice call is already existing, do not proceed further to avoid
1325 * disabling/enabling both RX and TX devices, CSD calls, etc.
1326 * Once the voice call done, the HDMI channels can be configured to
1327 * max channels of remaining use cases.
1328 */
1329 if (usecase->id == USECASE_VOICE_CALL) {
1330 ALOGD("%s: voice call is active, no change in HDMI channels",
1331 __func__);
1332 ret = false;
1333 break;
1334 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1335 ALOGD("%s: multi channel playback is active, "
1336 "no change in HDMI channels", __func__);
1337 ret = false;
1338 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001339 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001340 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001341 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1342 ", no change in HDMI channels", __func__,
1343 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001344 ret = false;
1345 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001346 }
1347 }
1348 }
1349 return ret;
1350}
1351
1352static int check_and_set_hdmi_channels(struct audio_device *adev,
1353 unsigned int channels)
1354{
1355 struct listnode *node;
1356 struct audio_usecase *usecase;
1357
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001358 unsigned int supported_channels = platform_edid_get_max_channels(
1359 adev->platform);
1360 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001361 /* Check if change in HDMI channel config is allowed */
1362 if (!allow_hdmi_channel_config(adev))
1363 return 0;
1364
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001365 if (channels > supported_channels)
1366 channels = supported_channels;
1367
Eric Laurent07eeafd2013-10-06 12:52:49 -07001368 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001369 ALOGD("%s: Requested channels are same as current channels(%d)",
1370 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001371 return 0;
1372 }
1373
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001374 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001375 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001376 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001377 adev->cur_hdmi_channels = channels;
1378
1379 /*
1380 * Deroute all the playback streams routed to HDMI so that
1381 * the back end is deactivated. Note that backend will not
1382 * be deactivated if any one stream is connected to it.
1383 */
1384 list_for_each(node, &adev->usecase_list) {
1385 usecase = node_to_item(node, struct audio_usecase, list);
1386 if (usecase->type == PCM_PLAYBACK &&
1387 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001388 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001389 }
1390 }
1391
1392 /*
1393 * Enable all the streams disabled above. Now the HDMI backend
1394 * will be activated with new channel configuration
1395 */
1396 list_for_each(node, &adev->usecase_list) {
1397 usecase = node_to_item(node, struct audio_usecase, list);
1398 if (usecase->type == PCM_PLAYBACK &&
1399 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001400 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 }
1402 }
1403
1404 return 0;
1405}
1406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407static int stop_output_stream(struct stream_out *out)
1408{
1409 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410 struct audio_usecase *uc_info;
1411 struct audio_device *adev = out->dev;
1412
Eric Laurent994a6932013-07-17 11:51:42 -07001413 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 uc_info = get_usecase_from_list(adev, out->usecase);
1416 if (uc_info == NULL) {
1417 ALOGE("%s: Could not find the usecase (%d) in the list",
1418 __func__, out->usecase);
1419 return -EINVAL;
1420 }
1421
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001422 if (is_offload_usecase(out->usecase) &&
1423 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001424 if (adev->visualizer_stop_output != NULL)
1425 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001426
1427 audio_extn_dts_remove_state_notifier_node(out->usecase);
1428
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001429 if (adev->offload_effects_stop_output != NULL)
1430 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1431 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001432
Eric Laurent150dbfe2013-02-27 14:31:02 -08001433 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001434 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435
1436 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001437 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001439 list_remove(&uc_info->list);
1440 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001442 if (is_offload_usecase(out->usecase) &&
1443 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1444 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1445 ALOGV("Disable passthrough , reset mixer to pcm");
1446 /* NO_PASSTHROUGH */
1447 out->compr_config.codec->compr_passthr = 0;
1448 audio_extn_dolby_set_hdmi_config(adev, out);
1449 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1450 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001451 /* Must be called after removing the usecase from list */
1452 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1453 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1454
Eric Laurent994a6932013-07-17 11:51:42 -07001455 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456 return ret;
1457}
1458
1459int start_output_stream(struct stream_out *out)
1460{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001461 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001462 int sink_channels = 0;
1463 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 struct audio_usecase *uc_info;
1465 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301466 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001468 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1469 ret = -EINVAL;
1470 goto error_config;
1471 }
1472
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301473 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1474 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1475 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301476
Naresh Tanniru80659832014-06-04 18:17:56 +05301477 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301478 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301479 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301480 goto error_config;
1481 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301482
Eric Laurentb23d5282013-05-14 15:27:20 -07001483 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 if (out->pcm_device_id < 0) {
1485 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1486 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001487 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001488 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 }
1490
1491 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001492
1493 if (!uc_info) {
1494 ret = -ENOMEM;
1495 goto error_config;
1496 }
1497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 uc_info->id = out->usecase;
1499 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001500 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 uc_info->devices = out->devices;
1502 uc_info->in_snd_device = SND_DEVICE_NONE;
1503 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001504 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001505 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001506 if (is_offload_usecase(out->usecase)) {
1507 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001508 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1509 }
1510 }
Mingming Yin9c041392014-05-01 15:37:31 -07001511 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1512 if (!strncmp("true", prop_value, 4)) {
1513 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001514 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1515 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001516 check_and_set_hdmi_channels(adev, sink_channels);
1517 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001518 if (is_offload_usecase(out->usecase)) {
1519 unsigned int ch_count = out->compr_config.codec->ch_in;
1520 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1521 /* backend channel config for passthrough stream is stereo */
1522 ch_count = 2;
1523 check_and_set_hdmi_channels(adev, ch_count);
1524 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001525 check_and_set_hdmi_channels(adev, out->config.channels);
1526 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001527 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001528 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001529 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531 select_devices(adev, out->usecase);
1532
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001533 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1534 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001535 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001536 unsigned int flags = PCM_OUT;
1537 unsigned int pcm_open_retry_count = 0;
1538 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1539 flags |= PCM_MMAP | PCM_NOIRQ;
1540 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1541 } else
1542 flags |= PCM_MONOTONIC;
1543
1544 while (1) {
1545 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1546 flags, &out->config);
1547 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1548 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1549 if (out->pcm != NULL) {
1550 pcm_close(out->pcm);
1551 out->pcm = NULL;
1552 }
1553 if (pcm_open_retry_count-- == 0) {
1554 ret = -EIO;
1555 goto error_open;
1556 }
1557 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1558 continue;
1559 }
1560 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001561 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001562 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1563 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001564 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001565 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1566 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001568 out->compr = compress_open(adev->snd_card,
1569 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001570 COMPRESS_IN, &out->compr_config);
1571 if (out->compr && !is_compress_ready(out->compr)) {
1572 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1573 compress_close(out->compr);
1574 out->compr = NULL;
1575 ret = -EIO;
1576 goto error_open;
1577 }
1578 if (out->offload_callback)
1579 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001580
Fred Oh3f43e742015-03-04 18:42:34 -08001581 /* Since small bufs uses blocking writes, a write will be blocked
1582 for the default max poll time (20s) in the event of an SSR.
1583 Reduce the poll time to observe and deal with SSR faster.
1584 */
1585 if (out->use_small_bufs) {
1586 compress_set_max_poll_wait(out->compr, 1000);
1587 }
1588
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001589 audio_extn_dts_create_state_notifier_node(out->usecase);
1590 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1591 popcount(out->channel_mask),
1592 out->playback_started);
1593
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001594#ifdef DS1_DOLBY_DDP_ENABLED
1595 if (audio_extn_is_dolby_format(out->format))
1596 audio_extn_dolby_send_ddp_endp_params(adev);
1597#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001598 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1599 if (adev->visualizer_start_output != NULL)
1600 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1601 if (adev->offload_effects_start_output != NULL)
1602 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001603 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001604 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 }
Eric Laurent994a6932013-07-17 11:51:42 -07001606 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001608error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001609 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001610error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612}
1613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614static int check_input_parameters(uint32_t sample_rate,
1615 audio_format_t format,
1616 int channel_count)
1617{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001618 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001620 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001621 !voice_extn_compress_voip_is_format_supported(format) &&
1622 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001623
1624 switch (channel_count) {
1625 case 1:
1626 case 2:
1627 case 6:
1628 break;
1629 default:
1630 ret = -EINVAL;
1631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632
1633 switch (sample_rate) {
1634 case 8000:
1635 case 11025:
1636 case 12000:
1637 case 16000:
1638 case 22050:
1639 case 24000:
1640 case 32000:
1641 case 44100:
1642 case 48000:
1643 break;
1644 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001645 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
1647
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001648 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649}
1650
1651static size_t get_input_buffer_size(uint32_t sample_rate,
1652 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001653 int channel_count,
1654 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655{
1656 size_t size = 0;
1657
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001658 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1659 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001661 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001662 if (is_low_latency)
1663 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001664 /* ToDo: should use frame_size computed based on the format and
1665 channel_count here. */
1666 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001668 /* make sure the size is multiple of 32 bytes
1669 * At 48 kHz mono 16-bit PCM:
1670 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1671 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1672 */
1673 size += 0x1f;
1674 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001675
1676 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677}
1678
1679static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1680{
1681 struct stream_out *out = (struct stream_out *)stream;
1682
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001683 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684}
1685
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001686static int out_set_sample_rate(struct audio_stream *stream __unused,
1687 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688{
1689 return -ENOSYS;
1690}
1691
1692static size_t out_get_buffer_size(const struct audio_stream *stream)
1693{
1694 struct stream_out *out = (struct stream_out *)stream;
1695
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001696 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001697 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001698 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1699 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001700
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001701 return out->config.period_size *
1702 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703}
1704
1705static uint32_t out_get_channels(const struct audio_stream *stream)
1706{
1707 struct stream_out *out = (struct stream_out *)stream;
1708
1709 return out->channel_mask;
1710}
1711
1712static audio_format_t out_get_format(const struct audio_stream *stream)
1713{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 struct stream_out *out = (struct stream_out *)stream;
1715
1716 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717}
1718
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001719static int out_set_format(struct audio_stream *stream __unused,
1720 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721{
1722 return -ENOSYS;
1723}
1724
1725static int out_standby(struct audio_stream *stream)
1726{
1727 struct stream_out *out = (struct stream_out *)stream;
1728 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001729
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301730 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1731 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001732 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1733 /* Ignore standby in case of voip call because the voip output
1734 * stream is closed in adev_close_output_stream()
1735 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301736 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001737 return 0;
1738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001740 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001742 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001744 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001745 if (out->pcm) {
1746 pcm_close(out->pcm);
1747 out->pcm = NULL;
1748 }
1749 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001750 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001752 out->gapless_mdata.encoder_delay = 0;
1753 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 if (out->compr != NULL) {
1755 compress_close(out->compr);
1756 out->compr = NULL;
1757 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001760 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 }
1762 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001763 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764 return 0;
1765}
1766
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001767static int out_dump(const struct audio_stream *stream __unused,
1768 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769{
1770 return 0;
1771}
1772
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001773static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1774{
1775 int ret = 0;
1776 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001777 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001778
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001779 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001780 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001781 return -EINVAL;
1782 }
1783
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001784 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1785 if (ret >= 0) {
1786 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1787 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1788 ALOGV("ADTS format is set in offload mode");
1789 }
1790 out->send_new_metadata = 1;
1791 }
1792
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301793 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001794
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001795 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1796 if(ret >= 0)
1797 is_meta_data_params = true;
1798 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301799 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001800 is_meta_data_params = true;
1801 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301802 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001803 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001804 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1805 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001806 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301807 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001808 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001809 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1810 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001811 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301812 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001813 }
1814
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001815 if(!is_meta_data_params) {
1816 ALOGV("%s: Not gapless meta data params", __func__);
1817 return 0;
1818 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001819 out->send_new_metadata = 1;
1820 ALOGV("%s new encoder delay %u and padding %u", __func__,
1821 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1822
1823 return 0;
1824}
1825
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001826static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1827{
1828 return out == adev->primary_output || out == adev->voice_tx_output;
1829}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1832{
1833 struct stream_out *out = (struct stream_out *)stream;
1834 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001835 struct audio_usecase *usecase;
1836 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837 struct str_parms *parms;
1838 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001839 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001840 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841
sangwoobc677242013-08-08 16:53:43 +09001842 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001843 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301845 if (!parms)
1846 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001847 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1848 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001851 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001853 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301854 * When HDMI cable is unplugged/usb hs is disconnected the
1855 * music playback is paused and the policy manager sends routing=0
1856 * But the audioflingercontinues to write data until standby time
1857 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001858 * Avoid this by routing audio to speaker until standby.
1859 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301860 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1861 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001862 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001863 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1864 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001865 }
1866
1867 /*
1868 * select_devices() call below switches all the usecases on the same
1869 * backend to the new device. Refer to check_usecases_codec_backend() in
1870 * the select_devices(). But how do we undo this?
1871 *
1872 * For example, music playback is active on headset (deep-buffer usecase)
1873 * and if we go to ringtones and select a ringtone, low-latency usecase
1874 * will be started on headset+speaker. As we can't enable headset+speaker
1875 * and headset devices at the same time, select_devices() switches the music
1876 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1877 * So when the ringtone playback is completed, how do we undo the same?
1878 *
1879 * We are relying on the out_set_parameters() call on deep-buffer output,
1880 * once the ringtone playback is ended.
1881 * NOTE: We should not check if the current devices are same as new devices.
1882 * Because select_devices() must be called to switch back the music
1883 * playback to headset.
1884 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001885 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 out->devices = val;
1887
1888 if (!out->standby)
1889 select_devices(adev, out->usecase);
1890
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001891 if (output_drives_call(adev, out)) {
1892 if(!voice_is_in_call(adev)) {
1893 if (adev->mode == AUDIO_MODE_IN_CALL) {
1894 adev->current_call_output = out;
1895 ret = voice_start_call(adev);
1896 }
1897 } else {
1898 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001899 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001900 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001901 }
1902 }
1903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001905 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001907
1908 if (out == adev->primary_output) {
1909 pthread_mutex_lock(&adev->lock);
1910 audio_extn_set_parameters(adev, parms);
1911 pthread_mutex_unlock(&adev->lock);
1912 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001913 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001914 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001915 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001916
1917 audio_extn_dts_create_state_notifier_node(out->usecase);
1918 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1919 popcount(out->channel_mask),
1920 out->playback_started);
1921
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001922 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001923 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301926error:
Eric Laurent994a6932013-07-17 11:51:42 -07001927 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 return ret;
1929}
1930
1931static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1932{
1933 struct stream_out *out = (struct stream_out *)stream;
1934 struct str_parms *query = str_parms_create_str(keys);
1935 char *str;
1936 char value[256];
1937 struct str_parms *reply = str_parms_create();
1938 size_t i, j;
1939 int ret;
1940 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001941
1942 if (!query || !reply) {
1943 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1944 return NULL;
1945 }
1946
Eric Laurent994a6932013-07-17 11:51:42 -07001947 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1949 if (ret >= 0) {
1950 value[0] = '\0';
1951 i = 0;
1952 while (out->supported_channel_masks[i] != 0) {
1953 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1954 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1955 if (!first) {
1956 strcat(value, "|");
1957 }
1958 strcat(value, out_channels_name_to_enum_table[j].name);
1959 first = false;
1960 break;
1961 }
1962 }
1963 i++;
1964 }
1965 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1966 str = str_parms_to_str(reply);
1967 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001968 voice_extn_out_get_parameters(out, query, reply);
1969 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001970 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001971 free(str);
1972 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001973 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001975
1976 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1977 if (ret >= 0) {
1978 value[0] = '\0';
1979 i = 0;
1980 first = true;
1981 while (out->supported_formats[i] != 0) {
1982 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1983 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1984 if (!first) {
1985 strcat(value, "|");
1986 }
1987 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
1988 first = false;
1989 break;
1990 }
1991 }
1992 i++;
1993 }
1994 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
1995 str = str_parms_to_str(reply);
1996 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997 str_parms_destroy(query);
1998 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001999 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 return str;
2001}
2002
2003static uint32_t out_get_latency(const struct audio_stream_out *stream)
2004{
2005 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002006 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007
Alexy Josephaa54c872014-12-03 02:46:47 -08002008 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002009 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002010 } else {
2011 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002012 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002013 }
2014
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302015 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002016 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017}
2018
2019static int out_set_volume(struct audio_stream_out *stream, float left,
2020 float right)
2021{
Eric Laurenta9024de2013-04-04 09:19:12 -07002022 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002023 int volume[2];
2024
Eric Laurenta9024de2013-04-04 09:19:12 -07002025 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2026 /* only take left channel into account: the API is for stereo anyway */
2027 out->muted = (left == 0.0f);
2028 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002029 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002030 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2031 /*
2032 * Set mute or umute on HDMI passthrough stream.
2033 * Only take left channel into account.
2034 * Mute is 0 and unmute 1
2035 */
2036 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2037 } else {
2038 char mixer_ctl_name[128];
2039 struct audio_device *adev = out->dev;
2040 struct mixer_ctl *ctl;
2041 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002042 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002044 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2045 "Compress Playback %d Volume", pcm_device_id);
2046 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2047 if (!ctl) {
2048 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2049 __func__, mixer_ctl_name);
2050 return -EINVAL;
2051 }
2052 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2053 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2054 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2055 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002057 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 return -ENOSYS;
2060}
2061
2062static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2063 size_t bytes)
2064{
2065 struct stream_out *out = (struct stream_out *)stream;
2066 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302067 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002068 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302071
Naresh Tanniru80659832014-06-04 18:17:56 +05302072 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002073 // increase written size during SSR to avoid mismatch
2074 // with the written frames count in AF
2075 if (!is_offload_usecase(out->usecase))
2076 out->written += bytes / (out->config.channels * sizeof(short));
2077
Naresh Tanniru80659832014-06-04 18:17:56 +05302078 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302079 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302080 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302081 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002082 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302083 //during SSR for compress usecase we should return error to flinger
2084 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2085 pthread_mutex_unlock(&out->lock);
2086 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302087 }
2088 }
2089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002091 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002092 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002093 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2094 ret = voice_extn_compress_voip_start_output_stream(out);
2095 else
2096 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002097 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002100 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101 goto exit;
2102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002105 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002106 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002107 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002108 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002109 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2110 out->send_new_metadata = 0;
2111 }
2112
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302114 if (ret < 0)
2115 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002116 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002117 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302118 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302120 } else if (-ENETRESET == ret) {
2121 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2122 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2123 pthread_mutex_unlock(&out->lock);
2124 out_standby(&out->stream.common);
2125 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302127 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002129 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 out->playback_started = 1;
2131 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002132
2133 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2134 popcount(out->channel_mask),
2135 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 }
2137 pthread_mutex_unlock(&out->lock);
2138 return ret;
2139 } else {
2140 if (out->pcm) {
2141 if (out->muted)
2142 memset((void *)buffer, 0, bytes);
2143 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002144 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2145 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2146 else
2147 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302148 if (ret < 0)
2149 ret = -errno;
2150 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002151 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 }
2154
2155exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302156 /* ToDo: There may be a corner case when SSR happens back to back during
2157 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302158 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302159 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302160 }
2161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 pthread_mutex_unlock(&out->lock);
2163
2164 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002165 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002166 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302167 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302168 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302169 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302170 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302171 out->standby = true;
2172 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002174 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302175 out_get_sample_rate(&out->stream.common));
2176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 }
2178 return bytes;
2179}
2180
2181static int out_get_render_position(const struct audio_stream_out *stream,
2182 uint32_t *dsp_frames)
2183{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002184 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302185 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002186
2187 if (dsp_frames == NULL)
2188 return -EINVAL;
2189
2190 *dsp_frames = 0;
2191 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002192 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002193 pthread_mutex_lock(&out->lock);
2194 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302195 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302197 if (ret < 0)
2198 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002199 ALOGVV("%s rendered frames %d sample_rate %d",
2200 __func__, *dsp_frames, out->sample_rate);
2201 }
2202 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302203 if (-ENETRESET == ret) {
2204 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2205 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2206 return -EINVAL;
2207 } else if(ret < 0) {
2208 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2209 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302210 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2211 /*
2212 * Handle corner case where compress session is closed during SSR
2213 * and timestamp is queried
2214 */
2215 ALOGE(" ERROR: sound card not active, return error");
2216 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302217 } else {
2218 return 0;
2219 }
Zhou Song32a556e2015-05-05 10:46:56 +08002220 } else if (audio_is_linear_pcm(out->format)) {
2221 *dsp_frames = out->written;
2222 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223 } else
2224 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225}
2226
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002227static int out_add_audio_effect(const struct audio_stream *stream __unused,
2228 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229{
2230 return 0;
2231}
2232
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002233static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2234 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235{
2236 return 0;
2237}
2238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002239static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2240 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241{
2242 return -EINVAL;
2243}
2244
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002245static int out_get_presentation_position(const struct audio_stream_out *stream,
2246 uint64_t *frames, struct timespec *timestamp)
2247{
2248 struct stream_out *out = (struct stream_out *)stream;
2249 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002250 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002251
2252 pthread_mutex_lock(&out->lock);
2253
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002254 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002255 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302256 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002257 &out->sample_rate);
2258 ALOGVV("%s rendered frames %ld sample_rate %d",
2259 __func__, dsp_frames, out->sample_rate);
2260 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302261 if (ret < 0)
2262 ret = -errno;
2263 if (-ENETRESET == ret) {
2264 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2265 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2266 ret = -EINVAL;
2267 } else
2268 ret = 0;
2269
Eric Laurent949a0892013-09-20 09:20:13 -07002270 /* this is the best we can do */
2271 clock_gettime(CLOCK_MONOTONIC, timestamp);
2272 }
2273 } else {
2274 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002275 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002276 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2277 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002278 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002279 // This adjustment accounts for buffering after app processor.
2280 // It is based on estimated DSP latency per use case, rather than exact.
2281 signed_frames -=
2282 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2283
Eric Laurent949a0892013-09-20 09:20:13 -07002284 // It would be unusual for this value to be negative, but check just in case ...
2285 if (signed_frames >= 0) {
2286 *frames = signed_frames;
2287 ret = 0;
2288 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002289 }
2290 }
2291 }
2292
2293 pthread_mutex_unlock(&out->lock);
2294
2295 return ret;
2296}
2297
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002298static int out_set_callback(struct audio_stream_out *stream,
2299 stream_callback_t callback, void *cookie)
2300{
2301 struct stream_out *out = (struct stream_out *)stream;
2302
2303 ALOGV("%s", __func__);
2304 pthread_mutex_lock(&out->lock);
2305 out->offload_callback = callback;
2306 out->offload_cookie = cookie;
2307 pthread_mutex_unlock(&out->lock);
2308 return 0;
2309}
2310
2311static int out_pause(struct audio_stream_out* stream)
2312{
2313 struct stream_out *out = (struct stream_out *)stream;
2314 int status = -ENOSYS;
2315 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002316 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002317 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002318 pthread_mutex_lock(&out->lock);
2319 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302320 struct audio_device *adev = out->dev;
2321 int snd_scard_state = get_snd_card_state(adev);
2322
2323 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2324 status = compress_pause(out->compr);
2325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002326 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002327
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302328 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002329 audio_extn_dts_notify_playback_state(out->usecase, 0,
2330 out->sample_rate, popcount(out->channel_mask),
2331 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002332 }
2333 pthread_mutex_unlock(&out->lock);
2334 }
2335 return status;
2336}
2337
2338static int out_resume(struct audio_stream_out* stream)
2339{
2340 struct stream_out *out = (struct stream_out *)stream;
2341 int status = -ENOSYS;
2342 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002343 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002344 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 status = 0;
2346 pthread_mutex_lock(&out->lock);
2347 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302348 struct audio_device *adev = out->dev;
2349 int snd_scard_state = get_snd_card_state(adev);
2350
2351 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2352 status = compress_resume(out->compr);
2353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002355
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302356 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002357 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2358 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 }
2360 pthread_mutex_unlock(&out->lock);
2361 }
2362 return status;
2363}
2364
2365static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2366{
2367 struct stream_out *out = (struct stream_out *)stream;
2368 int status = -ENOSYS;
2369 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002370 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 pthread_mutex_lock(&out->lock);
2372 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2373 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2374 else
2375 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2376 pthread_mutex_unlock(&out->lock);
2377 }
2378 return status;
2379}
2380
2381static int out_flush(struct audio_stream_out* stream)
2382{
2383 struct stream_out *out = (struct stream_out *)stream;
2384 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002385 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002386 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 pthread_mutex_lock(&out->lock);
2388 stop_compressed_output_l(out);
2389 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002390 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 return 0;
2392 }
2393 return -ENOSYS;
2394}
2395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396/** audio_stream_in implementation **/
2397static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2398{
2399 struct stream_in *in = (struct stream_in *)stream;
2400
2401 return in->config.rate;
2402}
2403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002404static int in_set_sample_rate(struct audio_stream *stream __unused,
2405 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406{
2407 return -ENOSYS;
2408}
2409
2410static size_t in_get_buffer_size(const struct audio_stream *stream)
2411{
2412 struct stream_in *in = (struct stream_in *)stream;
2413
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002414 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2415 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002416 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2417 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002418
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002419 return in->config.period_size *
2420 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421}
2422
2423static uint32_t in_get_channels(const struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426
2427 return in->channel_mask;
2428}
2429
2430static audio_format_t in_get_format(const struct audio_stream *stream)
2431{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002432 struct stream_in *in = (struct stream_in *)stream;
2433
2434 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435}
2436
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002437static int in_set_format(struct audio_stream *stream __unused,
2438 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439{
2440 return -ENOSYS;
2441}
2442
2443static int in_standby(struct audio_stream *stream)
2444{
2445 struct stream_in *in = (struct stream_in *)stream;
2446 struct audio_device *adev = in->dev;
2447 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302448 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2449 stream, in->usecase, use_case_table[in->usecase]);
2450
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002451 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2452 /* Ignore standby in case of voip call because the voip input
2453 * stream is closed in adev_close_input_stream()
2454 */
2455 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2456 return status;
2457 }
2458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002460 if (!in->standby && in->is_st_session) {
2461 ALOGD("%s: sound trigger pcm stop lab", __func__);
2462 audio_extn_sound_trigger_stop_lab(in);
2463 in->standby = 1;
2464 }
2465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002467 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002469 if (in->pcm) {
2470 pcm_close(in->pcm);
2471 in->pcm = NULL;
2472 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002474 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 }
2476 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002477 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 return status;
2479}
2480
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002481static int in_dump(const struct audio_stream *stream __unused,
2482 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483{
2484 return 0;
2485}
2486
2487static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2488{
2489 struct stream_in *in = (struct stream_in *)stream;
2490 struct audio_device *adev = in->dev;
2491 struct str_parms *parms;
2492 char *str;
2493 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002494 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302496 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 parms = str_parms_create_str(kvpairs);
2498
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302499 if (!parms)
2500 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002502 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002503
2504 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2505 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 val = atoi(value);
2507 /* no audio source uses val == 0 */
2508 if ((in->source != val) && (val != 0)) {
2509 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002510 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2511 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2512 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2513 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002514 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002515 err = voice_extn_compress_voip_open_input_stream(in);
2516 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002517 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002518 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002519 }
2520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 }
2522 }
2523
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002524 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2525 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002527 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 in->device = val;
2529 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002530 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002531 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 }
2533 }
2534
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002535done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538
2539 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302540error:
Eric Laurent994a6932013-07-17 11:51:42 -07002541 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 return ret;
2543}
2544
2545static char* in_get_parameters(const struct audio_stream *stream,
2546 const char *keys)
2547{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002548 struct stream_in *in = (struct stream_in *)stream;
2549 struct str_parms *query = str_parms_create_str(keys);
2550 char *str;
2551 char value[256];
2552 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002553
2554 if (!query || !reply) {
2555 ALOGE("in_get_parameters: failed to create query or reply");
2556 return NULL;
2557 }
2558
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002559 ALOGV("%s: enter: keys - %s", __func__, keys);
2560
2561 voice_extn_in_get_parameters(in, query, reply);
2562
2563 str = str_parms_to_str(reply);
2564 str_parms_destroy(query);
2565 str_parms_destroy(reply);
2566
2567 ALOGV("%s: exit: returns - %s", __func__, str);
2568 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569}
2570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002571static int in_set_gain(struct audio_stream_in *stream __unused,
2572 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573{
2574 return 0;
2575}
2576
2577static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2578 size_t bytes)
2579{
2580 struct stream_in *in = (struct stream_in *)stream;
2581 struct audio_device *adev = in->dev;
2582 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302583 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302586
2587 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302588 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302589 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302590 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302591 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002592 } else {
2593 if (in->is_st_session && !in->is_st_session_active) {
2594 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2595 ret= -EIO;;
2596 goto exit;
2597 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302598 }
2599 }
2600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002602 if (!in->is_st_session) {
2603 pthread_mutex_lock(&adev->lock);
2604 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2605 ret = voice_extn_compress_voip_start_input_stream(in);
2606 else
2607 ret = start_input_stream(in);
2608 pthread_mutex_unlock(&adev->lock);
2609 if (ret != 0) {
2610 goto exit;
2611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 }
2613 in->standby = 0;
2614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615
2616 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002617 if (audio_extn_ssr_get_enabled() &&
2618 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002619 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002620 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2621 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002622 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2623 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002624 else
2625 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302626 if (ret < 0)
2627 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 }
2629
2630 /*
2631 * Instead of writing zeroes here, we could trust the hardware
2632 * to always provide zeroes when muted.
2633 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302634 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2635 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 memset(buffer, 0, bytes);
2637
2638exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302639 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302640 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302641 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002642 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2643 session reading on LAB data. In this case do not set sound card state
2644 offline, instead mark this sound trigger session inactive to avoid
2645 further reading of LAB data from CPE driver. Marking the session
2646 inactive handles both CPE and ADSP SSR for sound trigger session */
2647 if (!in->is_st_session)
2648 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2649 else
2650 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302651 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 pthread_mutex_unlock(&in->lock);
2653
2654 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302655 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302656 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302657 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302658 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302659 in->standby = true;
2660 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302661 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002663 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002664 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302665 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 }
2667 return bytes;
2668}
2669
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002670static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671{
2672 return 0;
2673}
2674
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002675static int add_remove_audio_effect(const struct audio_stream *stream,
2676 effect_handle_t effect,
2677 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002679 struct stream_in *in = (struct stream_in *)stream;
2680 int status = 0;
2681 effect_descriptor_t desc;
2682
2683 status = (*effect)->get_descriptor(effect, &desc);
2684 if (status != 0)
2685 return status;
2686
2687 pthread_mutex_lock(&in->lock);
2688 pthread_mutex_lock(&in->dev->lock);
2689 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2690 in->enable_aec != enable &&
2691 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2692 in->enable_aec = enable;
2693 if (!in->standby)
2694 select_devices(in->dev, in->usecase);
2695 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002696 if (in->enable_ns != enable &&
2697 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2698 in->enable_ns = enable;
2699 if (!in->standby)
2700 select_devices(in->dev, in->usecase);
2701 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002702 pthread_mutex_unlock(&in->dev->lock);
2703 pthread_mutex_unlock(&in->lock);
2704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 return 0;
2706}
2707
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002708static int in_add_audio_effect(const struct audio_stream *stream,
2709 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710{
Eric Laurent994a6932013-07-17 11:51:42 -07002711 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712 return add_remove_audio_effect(stream, effect, true);
2713}
2714
2715static int in_remove_audio_effect(const struct audio_stream *stream,
2716 effect_handle_t effect)
2717{
Eric Laurent994a6932013-07-17 11:51:42 -07002718 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002719 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720}
2721
2722static int adev_open_output_stream(struct audio_hw_device *dev,
2723 audio_io_handle_t handle,
2724 audio_devices_t devices,
2725 audio_output_flags_t flags,
2726 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002727 struct audio_stream_out **stream_out,
2728 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
2730 struct audio_device *adev = (struct audio_device *)dev;
2731 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002732 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002733 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302736
2737 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2738 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2739 ALOGE(" sound card is not active rejecting compress output open request");
2740 return -EINVAL;
2741 }
2742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2744
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302745 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2746 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2747 devices, flags, &out->stream);
2748
2749
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002750 if (!out) {
2751 return -ENOMEM;
2752 }
2753
Haynes Mathew George204045b2015-02-25 20:32:03 -08002754 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2755 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 if (devices == AUDIO_DEVICE_NONE)
2758 devices = AUDIO_DEVICE_OUT_SPEAKER;
2759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 out->flags = flags;
2761 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002762 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002763 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002764 out->sample_rate = config->sample_rate;
2765 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2766 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002767 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002768 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002769 out->non_blocking = 0;
2770 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
2772 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002773 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2774 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2775 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2776
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002777 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002778 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2779 ret = read_hdmi_channel_masks(out);
2780
2781 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2782 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002783 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002784 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002785 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002786
2787 if (config->sample_rate == 0)
2788 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2789 if (config->channel_mask == 0)
2790 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2791
2792 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2795 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002797 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002799 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2800 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002801 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002802 ret = voice_extn_compress_voip_open_output_stream(out);
2803 if (ret != 0) {
2804 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2805 __func__, ret);
2806 goto error_open;
2807 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2809 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2810 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2811 ALOGE("%s: Unsupported Offload information", __func__);
2812 ret = -EINVAL;
2813 goto error_open;
2814 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002815
2816 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2817 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2818 ALOGV("read and update_pass through formats");
2819 ret = audio_extn_dolby_update_passt_formats(adev, out);
2820 if(ret != 0) {
2821 goto error_open;
2822 }
2823 if(config->offload_info.format == 0)
2824 config->offload_info.format = out->supported_formats[0];
2825 }
2826
Mingming Yin90310102013-11-13 16:57:00 -08002827 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002828 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829 ALOGE("%s: Unsupported audio format", __func__);
2830 ret = -EINVAL;
2831 goto error_open;
2832 }
2833
2834 out->compr_config.codec = (struct snd_codec *)
2835 calloc(1, sizeof(struct snd_codec));
2836
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002837 if (!out->compr_config.codec) {
2838 ret = -ENOMEM;
2839 goto error_open;
2840 }
2841
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002842 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 if (config->offload_info.channel_mask)
2844 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002845 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002847 config->offload_info.channel_mask = config->channel_mask;
2848 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002849 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850 out->sample_rate = config->offload_info.sample_rate;
2851
2852 out->stream.set_callback = out_set_callback;
2853 out->stream.pause = out_pause;
2854 out->stream.resume = out_resume;
2855 out->stream.drain = out_drain;
2856 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002857 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002859 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002860 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002861 audio_extn_dolby_get_snd_codec_id(adev, out,
2862 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002863 else
2864 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002866 if (audio_is_offload_pcm(config->offload_info.format)) {
2867 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002868 platform_get_pcm_offload_buffer_size(&config->offload_info);
2869 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2870 out->compr_config.fragment_size =
2871 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002872 } else {
2873 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002874 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002875 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2877 out->compr_config.codec->sample_rate =
Preetam Singh Ranawat0c3fc692015-05-14 15:19:10 +05302878 compress_get_alsa_rate(config->offload_info.sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 out->compr_config.codec->bit_rate =
2880 config->offload_info.bit_rate;
2881 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002882 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002884 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002885 /*TODO: Do we need to change it for passthrough */
2886 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887
Mingming Yin3ee55c62014-08-04 14:23:35 -07002888 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2889 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002890 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2891 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002892 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002893 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2894
Mingming Yin3ee55c62014-08-04 14:23:35 -07002895 if (out->bit_width == 24) {
2896 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2897 }
2898
Amit Shekhar6f461b12014-08-01 14:52:58 -07002899 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002900 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002902 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2903 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002904
Alexy Josephaa54c872014-12-03 02:46:47 -08002905 if (config->offload_info.use_small_bufs) {
2906 //this flag is set from framework only if its for PCM formats
2907 //no need to check for PCM format again
2908 out->non_blocking = 0;
2909 out->use_small_bufs = true;
2910 ALOGI("Keep write blocking for small buff: non_blockling %d",
2911 out->non_blocking);
2912 }
2913
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002914 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002915 out->offload_state = OFFLOAD_STATE_IDLE;
2916 out->playback_started = 0;
2917
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002918 audio_extn_dts_create_state_notifier_node(out->usecase);
2919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 create_offload_callback_thread(out);
2921 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2922 __func__, config->offload_info.version,
2923 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002924 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002925 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002926 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2927 ret = voice_check_and_set_incall_music_usecase(adev, out);
2928 if (ret != 0) {
2929 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2930 __func__, ret);
2931 goto error_open;
2932 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002933 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2934 if (config->sample_rate == 0)
2935 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2936 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2937 config->sample_rate != 8000) {
2938 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2939 ret = -EINVAL;
2940 goto error_open;
2941 }
2942 out->sample_rate = config->sample_rate;
2943 out->config.rate = config->sample_rate;
2944 if (config->format == AUDIO_FORMAT_DEFAULT)
2945 config->format = AUDIO_FORMAT_PCM_16_BIT;
2946 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2947 config->format = AUDIO_FORMAT_PCM_16_BIT;
2948 ret = -EINVAL;
2949 goto error_open;
2950 }
2951 out->format = config->format;
2952 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2953 out->config = pcm_config_afe_proxy_playback;
2954 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002955 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002956 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2958 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002959 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002960 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2961 format = AUDIO_FORMAT_PCM_16_BIT;
2962 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2963 out->config = pcm_config_deep_buffer;
2964 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002965 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002966 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002967 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002968 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002969 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002970 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 }
2972
Amit Shekhar1d896042014-10-03 13:16:09 -07002973 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2974 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002975 /* TODO remove this hardcoding and check why width is zero*/
2976 if (out->bit_width == 0)
2977 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002978 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2979 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002980 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002981 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002982 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2983 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2984 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002985 if(adev->primary_output == NULL)
2986 adev->primary_output = out;
2987 else {
2988 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002989 ret = -EEXIST;
2990 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002991 }
2992 }
2993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 /* Check if this usecase is already existing */
2995 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07002996 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2997 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003000 ret = -EEXIST;
3001 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 }
3003 pthread_mutex_unlock(&adev->lock);
3004
3005 out->stream.common.get_sample_rate = out_get_sample_rate;
3006 out->stream.common.set_sample_rate = out_set_sample_rate;
3007 out->stream.common.get_buffer_size = out_get_buffer_size;
3008 out->stream.common.get_channels = out_get_channels;
3009 out->stream.common.get_format = out_get_format;
3010 out->stream.common.set_format = out_set_format;
3011 out->stream.common.standby = out_standby;
3012 out->stream.common.dump = out_dump;
3013 out->stream.common.set_parameters = out_set_parameters;
3014 out->stream.common.get_parameters = out_get_parameters;
3015 out->stream.common.add_audio_effect = out_add_audio_effect;
3016 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3017 out->stream.get_latency = out_get_latency;
3018 out->stream.set_volume = out_set_volume;
3019 out->stream.write = out_write;
3020 out->stream.get_render_position = out_get_render_position;
3021 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003022 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003025 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003026 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027
3028 config->format = out->stream.common.get_format(&out->stream.common);
3029 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3030 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3031
3032 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303033 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3034 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003035
3036 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3037 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3038 popcount(out->channel_mask), out->playback_started);
3039
Eric Laurent994a6932013-07-17 11:51:42 -07003040 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003042
3043error_open:
3044 free(out);
3045 *stream_out = NULL;
3046 ALOGD("%s: exit: ret %d", __func__, ret);
3047 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048}
3049
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003050static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 struct audio_stream_out *stream)
3052{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 struct stream_out *out = (struct stream_out *)stream;
3054 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003055 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303057 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3058
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003059 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303060 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303062 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003063 if(ret != 0)
3064 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3065 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003066 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003067 out_standby(&stream->common);
3068
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003069 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003070 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003072 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 if (out->compr_config.codec != NULL)
3074 free(out->compr_config.codec);
3075 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003076
3077 if (adev->voice_tx_output == out)
3078 adev->voice_tx_output = NULL;
3079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 pthread_cond_destroy(&out->cond);
3081 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003083 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084}
3085
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003086static void close_compress_sessions(struct audio_device *adev)
3087{
Mingming Yin7b762e72015-03-04 13:47:32 -08003088 struct stream_out *out;
3089 struct listnode *node;
3090 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003091 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003092 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003093 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003094 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003095 if (usecase && usecase->stream.out) {
3096 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3097 out = usecase->stream.out;
3098 pthread_mutex_unlock(&adev->lock);
3099 out_standby(&out->stream.common);
3100 pthread_mutex_lock(&adev->lock);
3101 }
3102 }
3103 }
3104 pthread_mutex_unlock(&adev->lock);
3105}
3106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3108{
3109 struct audio_device *adev = (struct audio_device *)dev;
3110 struct str_parms *parms;
3111 char *str;
3112 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003113 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003114 int ret;
3115 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003117 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303120 if (!parms)
3121 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003122 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3123 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303124 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303125 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303126 struct listnode *node;
3127 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303128 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303129 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003130 //close compress sessions on OFFLINE status
3131 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303132 } else if (strstr(snd_card_status, "ONLINE")) {
3133 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303134 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303135 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303136 }
3137
3138 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003139 status = voice_set_parameters(adev, parms);
3140 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003141 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003143 status = platform_set_parameters(adev->platform, parms);
3144 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003145 goto done;
3146
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003147 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3148 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003149 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3151 adev->bluetooth_nrec = true;
3152 else
3153 adev->bluetooth_nrec = false;
3154 }
3155
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003156 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3157 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3159 adev->screen_off = false;
3160 else
3161 adev->screen_off = true;
3162 }
3163
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003164 ret = str_parms_get_int(parms, "rotation", &val);
3165 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003166 bool reverse_speakers = false;
3167 switch(val) {
3168 // FIXME: note that the code below assumes that the speakers are in the correct placement
3169 // relative to the user when the device is rotated 90deg from its default rotation. This
3170 // assumption is device-specific, not platform-specific like this code.
3171 case 270:
3172 reverse_speakers = true;
3173 break;
3174 case 0:
3175 case 90:
3176 case 180:
3177 break;
3178 default:
3179 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003180 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003181 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003182 if (status == 0) {
3183 if (adev->speaker_lr_swap != reverse_speakers) {
3184 adev->speaker_lr_swap = reverse_speakers;
3185 // only update the selected device if there is active pcm playback
3186 struct audio_usecase *usecase;
3187 struct listnode *node;
3188 list_for_each(node, &adev->usecase_list) {
3189 usecase = node_to_item(node, struct audio_usecase, list);
3190 if (usecase->type == PCM_PLAYBACK) {
3191 select_devices(adev, usecase->id);
3192 break;
3193 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003194 }
3195 }
3196 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 }
3198
Mingming Yin514a8bc2014-07-29 15:22:21 -07003199 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3200 if (ret >= 0) {
3201 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3202 adev->bt_wb_speech_enabled = true;
3203 else
3204 adev->bt_wb_speech_enabled = false;
3205 }
3206
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003207 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3208 if (ret >= 0) {
3209 val = atoi(value);
3210 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3211 ALOGV("cache new edid");
3212 platform_cache_edid(adev->platform);
3213 }
3214 }
3215
3216 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3217 if (ret >= 0) {
3218 val = atoi(value);
3219 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3220 ALOGV("invalidate cached edid");
3221 platform_invalidate_edid(adev->platform);
3222 }
3223 }
3224
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003225 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003226
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003227done:
3228 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003229 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303230error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003231 ALOGV("%s: exit with code(%d)", __func__, status);
3232 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233}
3234
3235static char* adev_get_parameters(const struct audio_hw_device *dev,
3236 const char *keys)
3237{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003238 struct audio_device *adev = (struct audio_device *)dev;
3239 struct str_parms *reply = str_parms_create();
3240 struct str_parms *query = str_parms_create_str(keys);
3241 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303242 char value[256] = {0};
3243 int ret = 0;
3244
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003245 if (!query || !reply) {
3246 ALOGE("adev_get_parameters: failed to create query or reply");
3247 return NULL;
3248 }
3249
Naresh Tannirud7205b62014-06-20 02:54:48 +05303250 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3251 sizeof(value));
3252 if (ret >=0) {
3253 int val = 1;
3254 pthread_mutex_lock(&adev->snd_card_status.lock);
3255 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3256 val = 0;
3257 pthread_mutex_unlock(&adev->snd_card_status.lock);
3258 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3259 goto exit;
3260 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003261
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003262 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003263 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003264 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003265 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303266 pthread_mutex_unlock(&adev->lock);
3267
Naresh Tannirud7205b62014-06-20 02:54:48 +05303268exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003269 str = str_parms_to_str(reply);
3270 str_parms_destroy(query);
3271 str_parms_destroy(reply);
3272
3273 ALOGV("%s: exit: returns - %s", __func__, str);
3274 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003277static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278{
3279 return 0;
3280}
3281
3282static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3283{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003284 int ret;
3285 struct audio_device *adev = (struct audio_device *)dev;
3286 pthread_mutex_lock(&adev->lock);
3287 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003288 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003289 pthread_mutex_unlock(&adev->lock);
3290 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291}
3292
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003293static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3294 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295{
3296 return -ENOSYS;
3297}
3298
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003299static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3300 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301{
3302 return -ENOSYS;
3303}
3304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003305static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3306 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
3308 return -ENOSYS;
3309}
3310
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003311static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3312 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return -ENOSYS;
3315}
3316
3317static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3318{
3319 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 pthread_mutex_lock(&adev->lock);
3322 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003323 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003325 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3326 voice_is_in_call(adev)) {
3327 voice_stop_call(adev);
3328 adev->current_call_output = NULL;
3329 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 }
3331 pthread_mutex_unlock(&adev->lock);
3332 return 0;
3333}
3334
3335static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3336{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003337 int ret;
3338
3339 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003340 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003341 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3342 pthread_mutex_unlock(&adev->lock);
3343
3344 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
3347static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3348{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003349 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 return 0;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 const struct audio_config *config)
3355{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003356 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003358 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3359 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360}
3361
3362static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003363 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364 audio_devices_t devices,
3365 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003366 struct audio_stream_in **stream_in,
3367 audio_input_flags_t flags __unused,
3368 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003369 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370{
3371 struct audio_device *adev = (struct audio_device *)dev;
3372 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003373 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003374 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003375 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 *stream_in = NULL;
3378 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3379 return -EINVAL;
3380
3381 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003382
3383 if (!in) {
3384 ALOGE("failed to allocate input stream");
3385 return -ENOMEM;
3386 }
3387
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303388 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003389 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3390 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003392 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 in->stream.common.get_sample_rate = in_get_sample_rate;
3395 in->stream.common.set_sample_rate = in_set_sample_rate;
3396 in->stream.common.get_buffer_size = in_get_buffer_size;
3397 in->stream.common.get_channels = in_get_channels;
3398 in->stream.common.get_format = in_get_format;
3399 in->stream.common.set_format = in_set_format;
3400 in->stream.common.standby = in_standby;
3401 in->stream.common.dump = in_dump;
3402 in->stream.common.set_parameters = in_set_parameters;
3403 in->stream.common.get_parameters = in_get_parameters;
3404 in->stream.common.add_audio_effect = in_add_audio_effect;
3405 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3406 in->stream.set_gain = in_set_gain;
3407 in->stream.read = in_read;
3408 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3409
3410 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003411 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 in->standby = 1;
3414 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003415 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
3417 /* Update config params with the requested sample rate and channels */
3418 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003419 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3420 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3421 is_low_latency = true;
3422#if LOW_LATENCY_CAPTURE_USE_CASE
3423 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3424#endif
3425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003428 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003430 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303431 if (adev->mode != AUDIO_MODE_IN_CALL) {
3432 ret = -EINVAL;
3433 goto err_open;
3434 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003435 if (config->sample_rate == 0)
3436 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3437 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3438 config->sample_rate != 8000) {
3439 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3440 ret = -EINVAL;
3441 goto err_open;
3442 }
3443 if (config->format == AUDIO_FORMAT_DEFAULT)
3444 config->format = AUDIO_FORMAT_PCM_16_BIT;
3445 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3446 config->format = AUDIO_FORMAT_PCM_16_BIT;
3447 ret = -EINVAL;
3448 goto err_open;
3449 }
3450
3451 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3452 in->config = pcm_config_afe_proxy_record;
3453 in->config.channels = channel_count;
3454 in->config.rate = config->sample_rate;
3455 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003456 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003457 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003458 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3459 ret = -EINVAL;
3460 goto err_open;
3461 }
3462 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003463 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003464 }
Mingming Yine62d7842013-10-25 16:26:03 -07003465 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003466 audio_extn_compr_cap_format_supported(config->format) &&
3467 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003468 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003469 } else {
3470 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003471 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003472 buffer_size = get_input_buffer_size(config->sample_rate,
3473 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003474 channel_count,
3475 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003476 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003477 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3478 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3479 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3480 (in->config.rate == 8000 || in->config.rate == 16000) &&
3481 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3482 voice_extn_compress_voip_open_input_stream(in);
3483 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003484 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003486 /* This stream could be for sound trigger lab,
3487 get sound trigger pcm if present */
3488 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303489 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003492 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003493 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494
3495err_open:
3496 free(in);
3497 *stream_in = NULL;
3498 return ret;
3499}
3500
3501static void adev_close_input_stream(struct audio_hw_device *dev,
3502 struct audio_stream_in *stream)
3503{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003504 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003505 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003506 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303507
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303508 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003509
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303510 /* Disable echo reference while closing input stream */
3511 platform_set_echo_reference(adev->platform, false);
3512
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003513 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303514 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003515 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303516 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003517 if (ret != 0)
3518 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3519 __func__, ret);
3520 } else
3521 in_standby(&stream->common);
3522
Mingming Yin7b762e72015-03-04 13:47:32 -08003523 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003524 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003525 audio_extn_ssr_deinit();
3526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527
Mingming Yine62d7842013-10-25 16:26:03 -07003528 if(audio_extn_compr_cap_enabled() &&
3529 audio_extn_compr_cap_format_supported(in->config.format))
3530 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003531
3532 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 return;
3534}
3535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003536static int adev_dump(const audio_hw_device_t *device __unused,
3537 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
3539 return 0;
3540}
3541
3542static int adev_close(hw_device_t *device)
3543{
3544 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003545
3546 if (!adev)
3547 return 0;
3548
3549 pthread_mutex_lock(&adev_init_lock);
3550
3551 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003552 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003553 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003554 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003555 audio_route_free(adev->audio_route);
3556 free(adev->snd_dev_ref_cnt);
3557 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003558 free(device);
3559 adev = NULL;
3560 }
3561 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 return 0;
3563}
3564
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003565/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3566 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3567 * just that it _might_ work.
3568 */
3569static int period_size_is_plausible_for_low_latency(int period_size)
3570{
3571 switch (period_size) {
3572 case 160:
3573 case 240:
3574 case 320:
3575 case 480:
3576 return 1;
3577 default:
3578 return 0;
3579 }
3580}
3581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582static int adev_open(const hw_module_t *module, const char *name,
3583 hw_device_t **device)
3584{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003585 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003587 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3589
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003590 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003591 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003592 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003593 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003594 ALOGD("%s: returning existing instance of adev", __func__);
3595 ALOGD("%s: exit", __func__);
3596 pthread_mutex_unlock(&adev_init_lock);
3597 return 0;
3598 }
3599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 adev = calloc(1, sizeof(struct audio_device));
3601
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003602 if (!adev) {
3603 pthread_mutex_unlock(&adev_init_lock);
3604 return -ENOMEM;
3605 }
3606
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003607 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3610 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3611 adev->device.common.module = (struct hw_module_t *)module;
3612 adev->device.common.close = adev_close;
3613
3614 adev->device.init_check = adev_init_check;
3615 adev->device.set_voice_volume = adev_set_voice_volume;
3616 adev->device.set_master_volume = adev_set_master_volume;
3617 adev->device.get_master_volume = adev_get_master_volume;
3618 adev->device.set_master_mute = adev_set_master_mute;
3619 adev->device.get_master_mute = adev_get_master_mute;
3620 adev->device.set_mode = adev_set_mode;
3621 adev->device.set_mic_mute = adev_set_mic_mute;
3622 adev->device.get_mic_mute = adev_get_mic_mute;
3623 adev->device.set_parameters = adev_set_parameters;
3624 adev->device.get_parameters = adev_get_parameters;
3625 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3626 adev->device.open_output_stream = adev_open_output_stream;
3627 adev->device.close_output_stream = adev_close_output_stream;
3628 adev->device.open_input_stream = adev_open_input_stream;
3629 adev->device.close_input_stream = adev_close_input_stream;
3630 adev->device.dump = adev_dump;
3631
3632 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003634 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003635 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003638 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003639 /* adev->cur_hdmi_channels = 0; by calloc() */
Mingming Yin3ee55c62014-08-04 14:23:35 -07003640 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3641 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003642 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003643 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003644 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003645 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003646 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303647
3648 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3649 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003651 adev->platform = platform_init(adev);
3652 if (!adev->platform) {
3653 free(adev->snd_dev_ref_cnt);
3654 free(adev);
3655 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3656 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003657 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003658 return -EINVAL;
3659 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003660
Naresh Tanniru4c630392014-05-12 01:05:52 +05303661 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3662
Eric Laurentc4aef752013-09-12 17:45:53 -07003663 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3664 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3665 if (adev->visualizer_lib == NULL) {
3666 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3667 } else {
3668 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3669 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003670 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003671 "visualizer_hal_start_output");
3672 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003673 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003674 "visualizer_hal_stop_output");
3675 }
3676 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003677 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003678 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003679
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003680 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3681 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3682 if (adev->offload_effects_lib == NULL) {
3683 ALOGE("%s: DLOPEN failed for %s", __func__,
3684 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3685 } else {
3686 ALOGV("%s: DLOPEN successful for %s", __func__,
3687 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3688 adev->offload_effects_start_output =
3689 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3690 "offload_effects_bundle_hal_start_output");
3691 adev->offload_effects_stop_output =
3692 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3693 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003694 adev->offload_effects_set_hpx_state =
3695 (int (*)(bool))dlsym(adev->offload_effects_lib,
3696 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003697 }
3698 }
3699
Mingming Yin514a8bc2014-07-29 15:22:21 -07003700 adev->bt_wb_speech_enabled = false;
3701
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003702 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 *device = &adev->device.common;
3704
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003705 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3706 &adev->streams_output_cfg_list);
3707
Kiran Kandi910e1862013-10-29 13:29:42 -07003708 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003709
3710 char value[PROPERTY_VALUE_MAX];
3711 int trial;
3712 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3713 trial = atoi(value);
3714 if (period_size_is_plausible_for_low_latency(trial)) {
3715 pcm_config_low_latency.period_size = trial;
3716 pcm_config_low_latency.start_threshold = trial / 4;
3717 pcm_config_low_latency.avail_min = trial / 4;
3718 configured_low_latency_capture_period_size = trial;
3719 }
3720 }
3721 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3722 trial = atoi(value);
3723 if (period_size_is_plausible_for_low_latency(trial)) {
3724 configured_low_latency_capture_period_size = trial;
3725 }
3726 }
3727
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003728 pthread_mutex_unlock(&adev_init_lock);
3729
Eric Laurent994a6932013-07-17 11:51:42 -07003730 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 return 0;
3732}
3733
3734static struct hw_module_methods_t hal_module_methods = {
3735 .open = adev_open,
3736};
3737
3738struct audio_module HAL_MODULE_INFO_SYM = {
3739 .common = {
3740 .tag = HARDWARE_MODULE_TAG,
3741 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3742 .hal_api_version = HARDWARE_HAL_API_VERSION,
3743 .id = AUDIO_HARDWARE_MODULE_ID,
3744 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003745 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 .methods = &hal_module_methods,
3747 },
3748};