blob: 266dbd9e230c728a416d662eba9fb68b4639d875 [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
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800606 * specified usecase.
607 * For native(44.1k) usecases, we don't need this as it uses a different
608 * backend, but we need to make sure that we reconfigure the backend
609 * if there is bit_width change, this should not affect shared backend
610 * usecases.
611 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 for (i = 0; i < AUDIO_USECASE_MAX; i++)
613 switch_device[i] = false;
614
615 list_for_each(node, &adev->usecase_list) {
616 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800617 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 usecase != uc_info &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700619 (usecase->out_snd_device != snd_device || force_routing) &&
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800620 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND
621 && usecase->stream.out->sample_rate != OUTPUT_SAMPLING_RATE_44100) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
623 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700624 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700625 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 switch_device[usecase->id] = true;
627 num_uc_to_switch++;
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800628 } else if (usecase->type == PCM_PLAYBACK &&
629 usecase->stream.out->sample_rate ==
630 OUTPUT_SAMPLING_RATE_44100 && force_routing){
631 disable_audio_route(adev, usecase);
632 switch_device[usecase->id] = true;
633 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700634 }
635 }
636
637 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700638 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530640 /* Make sure the previous devices to be disabled first and then enable the
641 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700642 list_for_each(node, &adev->usecase_list) {
643 usecase = node_to_item(node, struct audio_usecase, list);
644 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700645 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 }
647 }
648
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700649 list_for_each(node, &adev->usecase_list) {
650 usecase = node_to_item(node, struct audio_usecase, list);
651 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700652 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700653 }
654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656 /* Re-route all the usecases on the shared backend other than the
657 specified usecase to new snd devices */
658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 /* Update the out_snd_device only before enabling the audio route */
661 if (switch_device[usecase->id] ) {
662 usecase->out_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800663 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530664 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 }
666 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700667 }
668}
669
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670static void check_and_route_capture_usecases(struct audio_device *adev,
671 struct audio_usecase *uc_info,
672 snd_device_t snd_device)
673{
674 struct listnode *node;
675 struct audio_usecase *usecase;
676 bool switch_device[AUDIO_USECASE_MAX];
677 int i, num_uc_to_switch = 0;
678
679 /*
680 * This function is to make sure that all the active capture usecases
681 * are always routed to the same input sound device.
682 * For example, if audio-record and voice-call usecases are currently
683 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
684 * is received for voice call then we have to make sure that audio-record
685 * usecase is also switched to earpiece i.e. voice-dmic-ef,
686 * because of the limitation that two devices cannot be enabled
687 * at the same time if they share the same backend.
688 */
689 for (i = 0; i < AUDIO_USECASE_MAX; i++)
690 switch_device[i] = false;
691
692 list_for_each(node, &adev->usecase_list) {
693 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800694 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700695 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700696 usecase->in_snd_device != snd_device &&
Avinash Vaishcc46ef12015-03-27 14:46:04 +0530697 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700698 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700699 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
700 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700701 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700702 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 switch_device[usecase->id] = true;
704 num_uc_to_switch++;
705 }
706 }
707
708 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700709 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700710
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530711 /* Make sure the previous devices to be disabled first and then enable the
712 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700713 list_for_each(node, &adev->usecase_list) {
714 usecase = node_to_item(node, struct audio_usecase, list);
715 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700716 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800717 }
718 }
719
720 list_for_each(node, &adev->usecase_list) {
721 usecase = node_to_item(node, struct audio_usecase, list);
722 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700723 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724 }
725 }
726
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700727 /* Re-route all the usecases on the shared backend other than the
728 specified usecase to new snd devices */
729 list_for_each(node, &adev->usecase_list) {
730 usecase = node_to_item(node, struct audio_usecase, list);
731 /* Update the in_snd_device only before enabling the audio route */
732 if (switch_device[usecase->id] ) {
733 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800734 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530735 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736 }
737 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700738 }
739}
740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800741/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700742static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700744 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700745 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746
747 switch (channels) {
748 /*
749 * Do not handle stereo output in Multi-channel cases
750 * Stereo case is handled in normal playback path
751 */
752 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700753 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
754 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
755 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
756 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
757 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800759 break;
760 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700761 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 break;
769 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700770 ALOGE("HDMI does not support multi channel playback");
771 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772 break;
773 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700774 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775}
776
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800777audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
778 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700779{
780 struct audio_usecase *usecase;
781 struct listnode *node;
782
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800785 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700786 ALOGV("%s: usecase id %d", __func__, usecase->id);
787 return usecase->id;
788 }
789 }
790 return USECASE_INVALID;
791}
792
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700793struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700794 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795{
796 struct audio_usecase *usecase;
797 struct listnode *node;
798
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
801 if (usecase->id == uc_id)
802 return usecase;
803 }
804 return NULL;
805}
806
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700807int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800809 snd_device_t out_snd_device = SND_DEVICE_NONE;
810 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811 struct audio_usecase *usecase = NULL;
812 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800813 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800814 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800815 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800816 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 usecase = get_usecase_from_list(adev, uc_id);
820 if (usecase == NULL) {
821 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
822 return -EINVAL;
823 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800825 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800826 (usecase->type == VOIP_CALL) ||
827 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700828 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800829 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700830 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 usecase->devices = usecase->stream.out->devices;
832 } else {
833 /*
834 * If the voice call is active, use the sound devices of voice call usecase
835 * so that it would not result any device switch. All the usecases will
836 * be switched to new device when select_devices() is called for voice call
837 * usecase. This is to avoid switching devices for voice call when
838 * check_usecases_codec_backend() is called below.
839 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700840 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700841 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800842 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700843 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
844 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 in_snd_device = vc_usecase->in_snd_device;
846 out_snd_device = vc_usecase->out_snd_device;
847 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800848 } else if (voice_extn_compress_voip_is_active(adev)) {
849 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700850 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530851 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700852 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800853 in_snd_device = voip_usecase->in_snd_device;
854 out_snd_device = voip_usecase->out_snd_device;
855 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800856 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800857 hfp_ucid = audio_extn_hfp_get_usecase();
858 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700859 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800860 in_snd_device = hfp_usecase->in_snd_device;
861 out_snd_device = hfp_usecase->out_snd_device;
862 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 }
864 if (usecase->type == PCM_PLAYBACK) {
865 usecase->devices = usecase->stream.out->devices;
866 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700867 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700868 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800869 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700870 if (usecase->stream.out == adev->primary_output &&
871 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800872 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
873 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700874 select_devices(adev, adev->active_input->usecase);
875 }
876 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 } else if (usecase->type == PCM_CAPTURE) {
878 usecase->devices = usecase->stream.in->device;
879 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700880 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700881 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530882 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
883 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
884 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
885 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700886 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800887 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700888 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
889 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700890 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894 }
895
896 if (out_snd_device == usecase->out_snd_device &&
897 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800898 return 0;
899 }
900
sangwoobc677242013-08-08 16:53:43 +0900901 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700902 out_snd_device, platform_get_snd_device_name(out_snd_device),
903 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 /*
906 * Limitation: While in call, to do a device switch we need to disable
907 * and enable both RX and TX devices though one of them is same as current
908 * device.
909 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700910 if ((usecase->type == VOICE_CALL) &&
911 (usecase->in_snd_device != SND_DEVICE_NONE) &&
912 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700913 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800914 }
915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 /* Disable current sound devices */
917 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700918 disable_audio_route(adev, usecase);
919 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920 }
921
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700923 disable_audio_route(adev, usecase);
924 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800925 }
926
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800927 /* Applicable only on the targets that has external modem.
928 * New device information should be sent to modem before enabling
929 * the devices to reduce in-call device switch time.
930 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700931 if ((usecase->type == VOICE_CALL) &&
932 (usecase->in_snd_device != SND_DEVICE_NONE) &&
933 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800934 status = platform_switch_voice_call_enable_device_config(adev->platform,
935 out_snd_device,
936 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700937 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800938
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 /* Enable new sound devices */
940 if (out_snd_device != SND_DEVICE_NONE) {
941 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
942 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700943 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 }
945
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 if (in_snd_device != SND_DEVICE_NONE) {
947 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700948 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700950
Avinash Vaish71a8b972014-07-24 15:36:33 +0530951 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700952 status = platform_switch_voice_call_device_post(adev->platform,
953 out_snd_device,
954 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530955 enable_audio_route_for_voice_usecases(adev, usecase);
956 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800957
sangwoo170731f2013-06-08 15:36:36 +0900958 usecase->in_snd_device = in_snd_device;
959 usecase->out_snd_device = out_snd_device;
960
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530961 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700962 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530963 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700964 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530965 usecase->stream.out->flags,
966 usecase->stream.out->format,
967 usecase->stream.out->sample_rate,
968 usecase->stream.out->bit_width,
969 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700970 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530971 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700972
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700973 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900974
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800975 /* Applicable only on the targets that has external modem.
976 * Enable device command should be sent to modem only after
977 * enabling voice call mixer controls
978 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700979 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800980 status = platform_switch_voice_call_usecase_route_post(adev->platform,
981 out_snd_device,
982 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530983 ALOGD("%s: done",__func__);
984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 return status;
986}
987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988static int stop_input_stream(struct stream_in *in)
989{
990 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 struct audio_usecase *uc_info;
992 struct audio_device *adev = in->dev;
993
Eric Laurentc8400632013-02-14 19:04:54 -0800994 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995
Eric Laurent994a6932013-07-17 11:51:42 -0700996 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700997 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998 uc_info = get_usecase_from_list(adev, in->usecase);
999 if (uc_info == NULL) {
1000 ALOGE("%s: Could not find the usecase (%d) in the list",
1001 __func__, in->usecase);
1002 return -EINVAL;
1003 }
1004
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001005 /* Close in-call recording streams */
1006 voice_check_and_stop_incall_rec_usecase(adev, in);
1007
Eric Laurent150dbfe2013-02-27 14:31:02 -08001008 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001009 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001010
1011 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001012 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001014 list_remove(&uc_info->list);
1015 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016
Eric Laurent994a6932013-07-17 11:51:42 -07001017 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 return ret;
1019}
1020
1021int start_input_stream(struct stream_in *in)
1022{
1023 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001024 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 struct audio_usecase *uc_info;
1026 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301027 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Mingming Yine62d7842013-10-25 16:26:03 -07001029 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301030 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1031 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001032
Naresh Tanniru80659832014-06-04 18:17:56 +05301033
1034 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301035 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301036 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301037 goto error_config;
1038 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301039
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001040 /* Check if source matches incall recording usecase criteria */
1041 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1042 if (ret)
1043 goto error_config;
1044 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001045 ALOGD("%s: Updated usecase(%d: %s)",
1046 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001047
Eric Laurentb23d5282013-05-14 15:27:20 -07001048 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049 if (in->pcm_device_id < 0) {
1050 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1051 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001052 ret = -EINVAL;
1053 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001055
1056 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001058
1059 if (!uc_info) {
1060 ret = -ENOMEM;
1061 goto error_config;
1062 }
1063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064 uc_info->id = in->usecase;
1065 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001066 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001067 uc_info->devices = in->device;
1068 uc_info->in_snd_device = SND_DEVICE_NONE;
1069 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001071 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301072 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074
Eric Laurentc8400632013-02-14 19:04:54 -08001075 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001076 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1077
1078 unsigned int flags = PCM_IN;
1079 unsigned int pcm_open_retry_count = 0;
1080
1081 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1082 flags |= PCM_MMAP | PCM_NOIRQ;
1083 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1084 }
1085
1086 while (1) {
1087 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1088 flags, &in->config);
1089 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1090 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1091 if (in->pcm != NULL) {
1092 pcm_close(in->pcm);
1093 in->pcm = NULL;
1094 }
1095 if (pcm_open_retry_count-- == 0) {
1096 ret = -EIO;
1097 goto error_open;
1098 }
1099 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1100 continue;
1101 }
1102 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301104 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301105
Eric Laurent994a6932013-07-17 11:51:42 -07001106 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001107 return ret;
1108
1109error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301111 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001112
1113error_config:
1114 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001116
1117 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118}
1119
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001120/* must be called with out->lock locked */
1121static int send_offload_cmd_l(struct stream_out* out, int command)
1122{
1123 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1124
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001125 if (!cmd) {
1126 ALOGE("failed to allocate mem for command 0x%x", command);
1127 return -ENOMEM;
1128 }
1129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001130 ALOGVV("%s %d", __func__, command);
1131
1132 cmd->cmd = command;
1133 list_add_tail(&out->offload_cmd_list, &cmd->node);
1134 pthread_cond_signal(&out->offload_cond);
1135 return 0;
1136}
1137
1138/* must be called iwth out->lock locked */
1139static void stop_compressed_output_l(struct stream_out *out)
1140{
1141 out->offload_state = OFFLOAD_STATE_IDLE;
1142 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001143 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001144 if (out->compr != NULL) {
1145 compress_stop(out->compr);
1146 while (out->offload_thread_blocked) {
1147 pthread_cond_wait(&out->cond, &out->lock);
1148 }
1149 }
1150}
1151
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001152bool is_offload_usecase(audio_usecase_t uc_id)
1153{
1154 unsigned int i;
1155 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1156 if (uc_id == offload_usecases[i])
1157 return true;
1158 }
1159 return false;
1160}
1161
1162static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1163{
1164 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1165 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1166 char value[PROPERTY_VALUE_MAX] = {0};
1167
1168 property_get("audio.offload.multiple.enabled", value, NULL);
1169 if (!(atoi(value) || !strncmp("true", value, 4)))
1170 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1171
1172 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1173 for (i = 0; i < num_usecase; i++) {
1174 if (!(adev->offload_usecases_state & (0x1<<i))) {
1175 adev->offload_usecases_state |= 0x1 << i;
1176 ret = offload_usecases[i];
1177 break;
1178 }
1179 }
1180 ALOGV("%s: offload usecase is %d", __func__, ret);
1181 return ret;
1182}
1183
1184static void free_offload_usecase(struct audio_device *adev,
1185 audio_usecase_t uc_id)
1186{
1187 unsigned int i;
1188 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1189 if (offload_usecases[i] == uc_id) {
1190 adev->offload_usecases_state &= ~(0x1<<i);
1191 break;
1192 }
1193 }
1194 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1195}
1196
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001197static void *offload_thread_loop(void *context)
1198{
1199 struct stream_out *out = (struct stream_out *) context;
1200 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001201 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1204 set_sched_policy(0, SP_FOREGROUND);
1205 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1206
1207 ALOGV("%s", __func__);
1208 pthread_mutex_lock(&out->lock);
1209 for (;;) {
1210 struct offload_cmd *cmd = NULL;
1211 stream_callback_event_t event;
1212 bool send_callback = false;
1213
1214 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1215 __func__, list_empty(&out->offload_cmd_list),
1216 out->offload_state);
1217 if (list_empty(&out->offload_cmd_list)) {
1218 ALOGV("%s SLEEPING", __func__);
1219 pthread_cond_wait(&out->offload_cond, &out->lock);
1220 ALOGV("%s RUNNING", __func__);
1221 continue;
1222 }
1223
1224 item = list_head(&out->offload_cmd_list);
1225 cmd = node_to_item(item, struct offload_cmd, node);
1226 list_remove(item);
1227
1228 ALOGVV("%s STATE %d CMD %d out->compr %p",
1229 __func__, out->offload_state, cmd->cmd, out->compr);
1230
1231 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1232 free(cmd);
1233 break;
1234 }
1235
1236 if (out->compr == NULL) {
1237 ALOGE("%s: Compress handle is NULL", __func__);
1238 pthread_cond_signal(&out->cond);
1239 continue;
1240 }
1241 out->offload_thread_blocked = true;
1242 pthread_mutex_unlock(&out->lock);
1243 send_callback = false;
1244 switch(cmd->cmd) {
1245 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001246 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001247 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001248 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001249 send_callback = true;
1250 event = STREAM_CBK_EVENT_WRITE_READY;
1251 break;
1252 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001253 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301254 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001255 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301256 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001257 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301258 if (ret < 0)
1259 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301260 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301261 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001262 compress_drain(out->compr);
1263 else
1264 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301265 if (ret != -ENETRESET) {
1266 send_callback = true;
1267 event = STREAM_CBK_EVENT_DRAIN_READY;
1268 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1269 } else
1270 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001271 break;
1272 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001273 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001274 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001275 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001276 send_callback = true;
1277 event = STREAM_CBK_EVENT_DRAIN_READY;
1278 break;
1279 default:
1280 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1281 break;
1282 }
1283 pthread_mutex_lock(&out->lock);
1284 out->offload_thread_blocked = false;
1285 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001286 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001287 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001288 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001289 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001290 free(cmd);
1291 }
1292
1293 pthread_cond_signal(&out->cond);
1294 while (!list_empty(&out->offload_cmd_list)) {
1295 item = list_head(&out->offload_cmd_list);
1296 list_remove(item);
1297 free(node_to_item(item, struct offload_cmd, node));
1298 }
1299 pthread_mutex_unlock(&out->lock);
1300
1301 return NULL;
1302}
1303
1304static int create_offload_callback_thread(struct stream_out *out)
1305{
1306 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1307 list_init(&out->offload_cmd_list);
1308 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1309 offload_thread_loop, out);
1310 return 0;
1311}
1312
1313static int destroy_offload_callback_thread(struct stream_out *out)
1314{
1315 pthread_mutex_lock(&out->lock);
1316 stop_compressed_output_l(out);
1317 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1318
1319 pthread_mutex_unlock(&out->lock);
1320 pthread_join(out->offload_thread, (void **) NULL);
1321 pthread_cond_destroy(&out->offload_cond);
1322
1323 return 0;
1324}
1325
Eric Laurent07eeafd2013-10-06 12:52:49 -07001326static bool allow_hdmi_channel_config(struct audio_device *adev)
1327{
1328 struct listnode *node;
1329 struct audio_usecase *usecase;
1330 bool ret = true;
1331
1332 list_for_each(node, &adev->usecase_list) {
1333 usecase = node_to_item(node, struct audio_usecase, list);
1334 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1335 /*
1336 * If voice call is already existing, do not proceed further to avoid
1337 * disabling/enabling both RX and TX devices, CSD calls, etc.
1338 * Once the voice call done, the HDMI channels can be configured to
1339 * max channels of remaining use cases.
1340 */
1341 if (usecase->id == USECASE_VOICE_CALL) {
1342 ALOGD("%s: voice call is active, no change in HDMI channels",
1343 __func__);
1344 ret = false;
1345 break;
1346 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1347 ALOGD("%s: multi channel playback is active, "
1348 "no change in HDMI channels", __func__);
1349 ret = false;
1350 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001351 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001352 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001353 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1354 ", no change in HDMI channels", __func__,
1355 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001356 ret = false;
1357 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001358 }
1359 }
1360 }
1361 return ret;
1362}
1363
1364static int check_and_set_hdmi_channels(struct audio_device *adev,
1365 unsigned int channels)
1366{
1367 struct listnode *node;
1368 struct audio_usecase *usecase;
1369
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001370 unsigned int supported_channels = platform_edid_get_max_channels(
1371 adev->platform);
1372 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001373 /* Check if change in HDMI channel config is allowed */
1374 if (!allow_hdmi_channel_config(adev))
1375 return 0;
1376
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001377 if (channels > supported_channels)
1378 channels = supported_channels;
1379
Eric Laurent07eeafd2013-10-06 12:52:49 -07001380 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001381 ALOGD("%s: Requested channels are same as current channels(%d)",
1382 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001383 return 0;
1384 }
1385
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001386 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001388 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001389 adev->cur_hdmi_channels = channels;
1390
1391 /*
1392 * Deroute all the playback streams routed to HDMI so that
1393 * the back end is deactivated. Note that backend will not
1394 * be deactivated if any one stream is connected to it.
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 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 }
1402 }
1403
1404 /*
1405 * Enable all the streams disabled above. Now the HDMI backend
1406 * will be activated with new channel configuration
1407 */
1408 list_for_each(node, &adev->usecase_list) {
1409 usecase = node_to_item(node, struct audio_usecase, list);
1410 if (usecase->type == PCM_PLAYBACK &&
1411 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001412 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001413 }
1414 }
1415
1416 return 0;
1417}
1418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419static int stop_output_stream(struct stream_out *out)
1420{
1421 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 struct audio_usecase *uc_info;
1423 struct audio_device *adev = out->dev;
1424
Eric Laurent994a6932013-07-17 11:51:42 -07001425 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001426 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 uc_info = get_usecase_from_list(adev, out->usecase);
1428 if (uc_info == NULL) {
1429 ALOGE("%s: Could not find the usecase (%d) in the list",
1430 __func__, out->usecase);
1431 return -EINVAL;
1432 }
1433
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001434 if (is_offload_usecase(out->usecase) &&
1435 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001436 if (adev->visualizer_stop_output != NULL)
1437 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001438
1439 audio_extn_dts_remove_state_notifier_node(out->usecase);
1440
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001441 if (adev->offload_effects_stop_output != NULL)
1442 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1443 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001444
Eric Laurent150dbfe2013-02-27 14:31:02 -08001445 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001446 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001447
1448 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001449 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001451 list_remove(&uc_info->list);
1452 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001454 if (is_offload_usecase(out->usecase) &&
1455 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1456 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1457 ALOGV("Disable passthrough , reset mixer to pcm");
1458 /* NO_PASSTHROUGH */
1459 out->compr_config.codec->compr_passthr = 0;
1460 audio_extn_dolby_set_hdmi_config(adev, out);
1461 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1462 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001463 /* Must be called after removing the usecase from list */
1464 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1465 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1466
Eric Laurent994a6932013-07-17 11:51:42 -07001467 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468 return ret;
1469}
1470
1471int start_output_stream(struct stream_out *out)
1472{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001474 int sink_channels = 0;
1475 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476 struct audio_usecase *uc_info;
1477 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301478 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001480 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1481 ret = -EINVAL;
1482 goto error_config;
1483 }
1484
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301485 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1486 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1487 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301488
Naresh Tanniru80659832014-06-04 18:17:56 +05301489 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301490 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301491 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301492 goto error_config;
1493 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301494
Eric Laurentb23d5282013-05-14 15:27:20 -07001495 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 if (out->pcm_device_id < 0) {
1497 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1498 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001499 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001500 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 }
1502
1503 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001504
1505 if (!uc_info) {
1506 ret = -ENOMEM;
1507 goto error_config;
1508 }
1509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 uc_info->id = out->usecase;
1511 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001512 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513 uc_info->devices = out->devices;
1514 uc_info->in_snd_device = SND_DEVICE_NONE;
1515 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001516 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001517 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001518 if (is_offload_usecase(out->usecase)) {
1519 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001520 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1521 }
1522 }
Mingming Yin9c041392014-05-01 15:37:31 -07001523 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1524 if (!strncmp("true", prop_value, 4)) {
1525 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001526 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1527 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001528 check_and_set_hdmi_channels(adev, sink_channels);
1529 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001530 if (is_offload_usecase(out->usecase)) {
1531 unsigned int ch_count = out->compr_config.codec->ch_in;
1532 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1533 /* backend channel config for passthrough stream is stereo */
1534 ch_count = 2;
1535 check_and_set_hdmi_channels(adev, ch_count);
1536 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001537 check_and_set_hdmi_channels(adev, out->config.channels);
1538 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001539 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001540 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001541 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001542
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 select_devices(adev, out->usecase);
1544
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001545 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1546 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001547 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001548 unsigned int flags = PCM_OUT;
1549 unsigned int pcm_open_retry_count = 0;
1550 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1551 flags |= PCM_MMAP | PCM_NOIRQ;
1552 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1553 } else
1554 flags |= PCM_MONOTONIC;
1555
1556 while (1) {
1557 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1558 flags, &out->config);
1559 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1560 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1561 if (out->pcm != NULL) {
1562 pcm_close(out->pcm);
1563 out->pcm = NULL;
1564 }
1565 if (pcm_open_retry_count-- == 0) {
1566 ret = -EIO;
1567 goto error_open;
1568 }
1569 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1570 continue;
1571 }
1572 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001573 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001574 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1575 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001576 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001577 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1578 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001580 out->compr = compress_open(adev->snd_card,
1581 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001582 COMPRESS_IN, &out->compr_config);
1583 if (out->compr && !is_compress_ready(out->compr)) {
1584 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1585 compress_close(out->compr);
1586 out->compr = NULL;
1587 ret = -EIO;
1588 goto error_open;
1589 }
1590 if (out->offload_callback)
1591 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001592
Fred Oh3f43e742015-03-04 18:42:34 -08001593 /* Since small bufs uses blocking writes, a write will be blocked
1594 for the default max poll time (20s) in the event of an SSR.
1595 Reduce the poll time to observe and deal with SSR faster.
1596 */
1597 if (out->use_small_bufs) {
1598 compress_set_max_poll_wait(out->compr, 1000);
1599 }
1600
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001601 audio_extn_dts_create_state_notifier_node(out->usecase);
1602 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1603 popcount(out->channel_mask),
1604 out->playback_started);
1605
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001606#ifdef DS1_DOLBY_DDP_ENABLED
1607 if (audio_extn_is_dolby_format(out->format))
1608 audio_extn_dolby_send_ddp_endp_params(adev);
1609#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001610 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1611 if (adev->visualizer_start_output != NULL)
1612 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1613 if (adev->offload_effects_start_output != NULL)
1614 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001615 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001616 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 }
Eric Laurent994a6932013-07-17 11:51:42 -07001618 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001619 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001620error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001622error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001623 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624}
1625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626static int check_input_parameters(uint32_t sample_rate,
1627 audio_format_t format,
1628 int channel_count)
1629{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001630 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001632 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001633 !voice_extn_compress_voip_is_format_supported(format) &&
1634 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001635
1636 switch (channel_count) {
1637 case 1:
1638 case 2:
1639 case 6:
1640 break;
1641 default:
1642 ret = -EINVAL;
1643 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644
1645 switch (sample_rate) {
1646 case 8000:
1647 case 11025:
1648 case 12000:
1649 case 16000:
1650 case 22050:
1651 case 24000:
1652 case 32000:
1653 case 44100:
1654 case 48000:
1655 break;
1656 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001657 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 }
1659
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001660 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661}
1662
1663static size_t get_input_buffer_size(uint32_t sample_rate,
1664 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001665 int channel_count,
1666 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667{
1668 size_t size = 0;
1669
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001670 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1671 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001673 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001674 if (is_low_latency)
1675 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001676 /* ToDo: should use frame_size computed based on the format and
1677 channel_count here. */
1678 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001680 /* make sure the size is multiple of 32 bytes
1681 * At 48 kHz mono 16-bit PCM:
1682 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1683 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1684 */
1685 size += 0x1f;
1686 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001687
1688 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001689}
1690
1691static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1692{
1693 struct stream_out *out = (struct stream_out *)stream;
1694
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001695 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696}
1697
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001698static int out_set_sample_rate(struct audio_stream *stream __unused,
1699 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700{
1701 return -ENOSYS;
1702}
1703
1704static size_t out_get_buffer_size(const struct audio_stream *stream)
1705{
1706 struct stream_out *out = (struct stream_out *)stream;
1707
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001708 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001709 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001710 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1711 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001712
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001713 return out->config.period_size *
1714 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715}
1716
1717static uint32_t out_get_channels(const struct audio_stream *stream)
1718{
1719 struct stream_out *out = (struct stream_out *)stream;
1720
1721 return out->channel_mask;
1722}
1723
1724static audio_format_t out_get_format(const struct audio_stream *stream)
1725{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726 struct stream_out *out = (struct stream_out *)stream;
1727
1728 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729}
1730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001731static int out_set_format(struct audio_stream *stream __unused,
1732 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733{
1734 return -ENOSYS;
1735}
1736
1737static int out_standby(struct audio_stream *stream)
1738{
1739 struct stream_out *out = (struct stream_out *)stream;
1740 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301742 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1743 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001744 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1745 /* Ignore standby in case of voip call because the voip output
1746 * stream is closed in adev_close_output_stream()
1747 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301748 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001749 return 0;
1750 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001754 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001756 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 if (out->pcm) {
1758 pcm_close(out->pcm);
1759 out->pcm = NULL;
1760 }
1761 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001762 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001764 out->gapless_mdata.encoder_delay = 0;
1765 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766 if (out->compr != NULL) {
1767 compress_close(out->compr);
1768 out->compr = NULL;
1769 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001772 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 }
1774 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001775 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 return 0;
1777}
1778
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001779static int out_dump(const struct audio_stream *stream __unused,
1780 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781{
1782 return 0;
1783}
1784
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001785static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1786{
1787 int ret = 0;
1788 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001789 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001790
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001791 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001792 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793 return -EINVAL;
1794 }
1795
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001796 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1797 if (ret >= 0) {
1798 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1799 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1800 ALOGV("ADTS format is set in offload mode");
1801 }
1802 out->send_new_metadata = 1;
1803 }
1804
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301805 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001806
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001807 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1808 if(ret >= 0)
1809 is_meta_data_params = true;
1810 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301811 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001812 is_meta_data_params = true;
1813 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301814 if(ret >= 0)
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001815 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001816 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1817 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001818 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301819 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001820 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001821 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1822 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001823 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301824 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001825 }
1826
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001827 if(!is_meta_data_params) {
1828 ALOGV("%s: Not gapless meta data params", __func__);
1829 return 0;
1830 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001831 out->send_new_metadata = 1;
1832 ALOGV("%s new encoder delay %u and padding %u", __func__,
1833 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1834
1835 return 0;
1836}
1837
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001838static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1839{
1840 return out == adev->primary_output || out == adev->voice_tx_output;
1841}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1844{
1845 struct stream_out *out = (struct stream_out *)stream;
1846 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001847 struct audio_usecase *usecase;
1848 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 struct str_parms *parms;
1850 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001851 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001852 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
sangwoobc677242013-08-08 16:53:43 +09001854 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301857 if (!parms)
1858 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001859 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1860 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001863 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001865 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301866 * When HDMI cable is unplugged/usb hs is disconnected the
1867 * music playback is paused and the policy manager sends routing=0
1868 * But the audioflingercontinues to write data until standby time
1869 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 * Avoid this by routing audio to speaker until standby.
1871 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301872 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1873 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001875 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1876 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 }
1878
1879 /*
1880 * select_devices() call below switches all the usecases on the same
1881 * backend to the new device. Refer to check_usecases_codec_backend() in
1882 * the select_devices(). But how do we undo this?
1883 *
1884 * For example, music playback is active on headset (deep-buffer usecase)
1885 * and if we go to ringtones and select a ringtone, low-latency usecase
1886 * will be started on headset+speaker. As we can't enable headset+speaker
1887 * and headset devices at the same time, select_devices() switches the music
1888 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1889 * So when the ringtone playback is completed, how do we undo the same?
1890 *
1891 * We are relying on the out_set_parameters() call on deep-buffer output,
1892 * once the ringtone playback is ended.
1893 * NOTE: We should not check if the current devices are same as new devices.
1894 * Because select_devices() must be called to switch back the music
1895 * playback to headset.
1896 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001897 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 out->devices = val;
1899
1900 if (!out->standby)
1901 select_devices(adev, out->usecase);
1902
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001903 if (output_drives_call(adev, out)) {
1904 if(!voice_is_in_call(adev)) {
1905 if (adev->mode == AUDIO_MODE_IN_CALL) {
1906 adev->current_call_output = out;
1907 ret = voice_start_call(adev);
1908 }
1909 } else {
1910 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001911 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001912 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001913 }
1914 }
1915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001917 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001919
1920 if (out == adev->primary_output) {
1921 pthread_mutex_lock(&adev->lock);
1922 audio_extn_set_parameters(adev, parms);
1923 pthread_mutex_unlock(&adev->lock);
1924 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001925 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001926 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001927 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001928
1929 audio_extn_dts_create_state_notifier_node(out->usecase);
1930 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1931 popcount(out->channel_mask),
1932 out->playback_started);
1933
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001934 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001935 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301938error:
Eric Laurent994a6932013-07-17 11:51:42 -07001939 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 return ret;
1941}
1942
1943static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1944{
1945 struct stream_out *out = (struct stream_out *)stream;
1946 struct str_parms *query = str_parms_create_str(keys);
1947 char *str;
1948 char value[256];
1949 struct str_parms *reply = str_parms_create();
1950 size_t i, j;
1951 int ret;
1952 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001953
1954 if (!query || !reply) {
1955 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1956 return NULL;
1957 }
1958
Eric Laurent994a6932013-07-17 11:51:42 -07001959 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1961 if (ret >= 0) {
1962 value[0] = '\0';
1963 i = 0;
1964 while (out->supported_channel_masks[i] != 0) {
1965 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1966 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1967 if (!first) {
1968 strcat(value, "|");
1969 }
1970 strcat(value, out_channels_name_to_enum_table[j].name);
1971 first = false;
1972 break;
1973 }
1974 }
1975 i++;
1976 }
1977 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1978 str = str_parms_to_str(reply);
1979 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001980 voice_extn_out_get_parameters(out, query, reply);
1981 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001982 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001983 free(str);
1984 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001985 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001987
1988 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1989 if (ret >= 0) {
1990 value[0] = '\0';
1991 i = 0;
1992 first = true;
1993 while (out->supported_formats[i] != 0) {
1994 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1995 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1996 if (!first) {
1997 strcat(value, "|");
1998 }
1999 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2000 first = false;
2001 break;
2002 }
2003 }
2004 i++;
2005 }
2006 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2007 str = str_parms_to_str(reply);
2008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 str_parms_destroy(query);
2010 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002011 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 return str;
2013}
2014
2015static uint32_t out_get_latency(const struct audio_stream_out *stream)
2016{
2017 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002018 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019
Alexy Josephaa54c872014-12-03 02:46:47 -08002020 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002021 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002022 } else {
2023 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002025 }
2026
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302027 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002028 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029}
2030
2031static int out_set_volume(struct audio_stream_out *stream, float left,
2032 float right)
2033{
Eric Laurenta9024de2013-04-04 09:19:12 -07002034 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 int volume[2];
2036
Eric Laurenta9024de2013-04-04 09:19:12 -07002037 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2038 /* only take left channel into account: the API is for stereo anyway */
2039 out->muted = (left == 0.0f);
2040 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002041 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002042 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2043 /*
2044 * Set mute or umute on HDMI passthrough stream.
2045 * Only take left channel into account.
2046 * Mute is 0 and unmute 1
2047 */
2048 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2049 } else {
2050 char mixer_ctl_name[128];
2051 struct audio_device *adev = out->dev;
2052 struct mixer_ctl *ctl;
2053 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002054 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002056 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2057 "Compress Playback %d Volume", pcm_device_id);
2058 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2059 if (!ctl) {
2060 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2061 __func__, mixer_ctl_name);
2062 return -EINVAL;
2063 }
2064 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2065 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2066 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2067 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002069 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 return -ENOSYS;
2072}
2073
2074static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2075 size_t bytes)
2076{
2077 struct stream_out *out = (struct stream_out *)stream;
2078 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302079 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002080 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302083
Naresh Tanniru80659832014-06-04 18:17:56 +05302084 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002085 // increase written size during SSR to avoid mismatch
2086 // with the written frames count in AF
2087 if (!is_offload_usecase(out->usecase))
2088 out->written += bytes / (out->config.channels * sizeof(short));
2089
Naresh Tanniru80659832014-06-04 18:17:56 +05302090 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302091 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302092 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302093 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002094 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302095 //during SSR for compress usecase we should return error to flinger
2096 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2097 pthread_mutex_unlock(&out->lock);
2098 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302099 }
2100 }
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002103 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002104 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002105 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2106 ret = voice_extn_compress_voip_start_output_stream(out);
2107 else
2108 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002109 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002112 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 goto exit;
2114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002117 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002118 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002119 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002120 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002121 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2122 out->send_new_metadata = 0;
2123 }
2124
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302126 if (ret < 0)
2127 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002129 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302130 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302132 } else if (-ENETRESET == ret) {
2133 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2134 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2135 pthread_mutex_unlock(&out->lock);
2136 out_standby(&out->stream.common);
2137 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302139 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002141 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 out->playback_started = 1;
2143 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002144
2145 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2146 popcount(out->channel_mask),
2147 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148 }
2149 pthread_mutex_unlock(&out->lock);
2150 return ret;
2151 } else {
2152 if (out->pcm) {
2153 if (out->muted)
2154 memset((void *)buffer, 0, bytes);
2155 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002156 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2157 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2158 else
2159 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302160 if (ret < 0)
2161 ret = -errno;
2162 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002163 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 }
2166
2167exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302168 /* ToDo: There may be a corner case when SSR happens back to back during
2169 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302170 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302171 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302172 }
2173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 pthread_mutex_unlock(&out->lock);
2175
2176 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002177 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002178 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302179 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302180 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302181 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302182 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302183 out->standby = true;
2184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002186 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302187 out_get_sample_rate(&out->stream.common));
2188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 }
2190 return bytes;
2191}
2192
2193static int out_get_render_position(const struct audio_stream_out *stream,
2194 uint32_t *dsp_frames)
2195{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002196 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302197 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002198
2199 if (dsp_frames == NULL)
2200 return -EINVAL;
2201
2202 *dsp_frames = 0;
2203 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002204 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 pthread_mutex_lock(&out->lock);
2206 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302207 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302209 if (ret < 0)
2210 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002211 ALOGVV("%s rendered frames %d sample_rate %d",
2212 __func__, *dsp_frames, out->sample_rate);
2213 }
2214 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302215 if (-ENETRESET == ret) {
2216 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2217 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2218 return -EINVAL;
2219 } else if(ret < 0) {
2220 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2221 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302222 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2223 /*
2224 * Handle corner case where compress session is closed during SSR
2225 * and timestamp is queried
2226 */
2227 ALOGE(" ERROR: sound card not active, return error");
2228 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 } else {
2230 return 0;
2231 }
Zhou Song32a556e2015-05-05 10:46:56 +08002232 } else if (audio_is_linear_pcm(out->format)) {
2233 *dsp_frames = out->written;
2234 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002235 } else
2236 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237}
2238
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002239static int out_add_audio_effect(const struct audio_stream *stream __unused,
2240 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241{
2242 return 0;
2243}
2244
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002245static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2246 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247{
2248 return 0;
2249}
2250
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002251static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2252 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253{
2254 return -EINVAL;
2255}
2256
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002257static int out_get_presentation_position(const struct audio_stream_out *stream,
2258 uint64_t *frames, struct timespec *timestamp)
2259{
2260 struct stream_out *out = (struct stream_out *)stream;
2261 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002262 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002263
2264 pthread_mutex_lock(&out->lock);
2265
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002266 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002267 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302268 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002269 &out->sample_rate);
2270 ALOGVV("%s rendered frames %ld sample_rate %d",
2271 __func__, dsp_frames, out->sample_rate);
2272 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302273 if (ret < 0)
2274 ret = -errno;
2275 if (-ENETRESET == ret) {
2276 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2277 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2278 ret = -EINVAL;
2279 } else
2280 ret = 0;
2281
Eric Laurent949a0892013-09-20 09:20:13 -07002282 /* this is the best we can do */
2283 clock_gettime(CLOCK_MONOTONIC, timestamp);
2284 }
2285 } else {
2286 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002287 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002288 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2289 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002290 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002291 // This adjustment accounts for buffering after app processor.
2292 // It is based on estimated DSP latency per use case, rather than exact.
2293 signed_frames -=
2294 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2295
Eric Laurent949a0892013-09-20 09:20:13 -07002296 // It would be unusual for this value to be negative, but check just in case ...
2297 if (signed_frames >= 0) {
2298 *frames = signed_frames;
2299 ret = 0;
2300 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002301 }
2302 }
2303 }
2304
2305 pthread_mutex_unlock(&out->lock);
2306
2307 return ret;
2308}
2309
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310static int out_set_callback(struct audio_stream_out *stream,
2311 stream_callback_t callback, void *cookie)
2312{
2313 struct stream_out *out = (struct stream_out *)stream;
2314
2315 ALOGV("%s", __func__);
2316 pthread_mutex_lock(&out->lock);
2317 out->offload_callback = callback;
2318 out->offload_cookie = cookie;
2319 pthread_mutex_unlock(&out->lock);
2320 return 0;
2321}
2322
2323static int out_pause(struct audio_stream_out* stream)
2324{
2325 struct stream_out *out = (struct stream_out *)stream;
2326 int status = -ENOSYS;
2327 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002328 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002329 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330 pthread_mutex_lock(&out->lock);
2331 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302332 struct audio_device *adev = out->dev;
2333 int snd_scard_state = get_snd_card_state(adev);
2334
2335 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2336 status = compress_pause(out->compr);
2337
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002339
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302340 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002341 audio_extn_dts_notify_playback_state(out->usecase, 0,
2342 out->sample_rate, popcount(out->channel_mask),
2343 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 }
2345 pthread_mutex_unlock(&out->lock);
2346 }
2347 return status;
2348}
2349
2350static int out_resume(struct audio_stream_out* stream)
2351{
2352 struct stream_out *out = (struct stream_out *)stream;
2353 int status = -ENOSYS;
2354 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002355 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002356 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 status = 0;
2358 pthread_mutex_lock(&out->lock);
2359 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302360 struct audio_device *adev = out->dev;
2361 int snd_scard_state = get_snd_card_state(adev);
2362
2363 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2364 status = compress_resume(out->compr);
2365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002367
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302368 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002369 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2370 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 }
2372 pthread_mutex_unlock(&out->lock);
2373 }
2374 return status;
2375}
2376
2377static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2378{
2379 struct stream_out *out = (struct stream_out *)stream;
2380 int status = -ENOSYS;
2381 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002382 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 pthread_mutex_lock(&out->lock);
2384 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2385 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2386 else
2387 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2388 pthread_mutex_unlock(&out->lock);
2389 }
2390 return status;
2391}
2392
2393static int out_flush(struct audio_stream_out* stream)
2394{
2395 struct stream_out *out = (struct stream_out *)stream;
2396 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002397 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002398 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 pthread_mutex_lock(&out->lock);
2400 stop_compressed_output_l(out);
2401 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002402 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 return 0;
2404 }
2405 return -ENOSYS;
2406}
2407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408/** audio_stream_in implementation **/
2409static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2410{
2411 struct stream_in *in = (struct stream_in *)stream;
2412
2413 return in->config.rate;
2414}
2415
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002416static int in_set_sample_rate(struct audio_stream *stream __unused,
2417 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418{
2419 return -ENOSYS;
2420}
2421
2422static size_t in_get_buffer_size(const struct audio_stream *stream)
2423{
2424 struct stream_in *in = (struct stream_in *)stream;
2425
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002426 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2427 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002428 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2429 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002430
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002431 return in->config.period_size *
2432 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433}
2434
2435static uint32_t in_get_channels(const struct audio_stream *stream)
2436{
2437 struct stream_in *in = (struct stream_in *)stream;
2438
2439 return in->channel_mask;
2440}
2441
2442static audio_format_t in_get_format(const struct audio_stream *stream)
2443{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002444 struct stream_in *in = (struct stream_in *)stream;
2445
2446 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447}
2448
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002449static int in_set_format(struct audio_stream *stream __unused,
2450 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451{
2452 return -ENOSYS;
2453}
2454
2455static int in_standby(struct audio_stream *stream)
2456{
2457 struct stream_in *in = (struct stream_in *)stream;
2458 struct audio_device *adev = in->dev;
2459 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302460 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2461 stream, in->usecase, use_case_table[in->usecase]);
2462
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002463 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2464 /* Ignore standby in case of voip call because the voip input
2465 * stream is closed in adev_close_input_stream()
2466 */
2467 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2468 return status;
2469 }
2470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002472 if (!in->standby && in->is_st_session) {
2473 ALOGD("%s: sound trigger pcm stop lab", __func__);
2474 audio_extn_sound_trigger_stop_lab(in);
2475 in->standby = 1;
2476 }
2477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002479 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002481 if (in->pcm) {
2482 pcm_close(in->pcm);
2483 in->pcm = NULL;
2484 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002486 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 }
2488 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002489 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 return status;
2491}
2492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002493static int in_dump(const struct audio_stream *stream __unused,
2494 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495{
2496 return 0;
2497}
2498
2499static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2500{
2501 struct stream_in *in = (struct stream_in *)stream;
2502 struct audio_device *adev = in->dev;
2503 struct str_parms *parms;
2504 char *str;
2505 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002506 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302508 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509 parms = str_parms_create_str(kvpairs);
2510
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302511 if (!parms)
2512 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002514 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002515
2516 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2517 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 val = atoi(value);
2519 /* no audio source uses val == 0 */
2520 if ((in->source != val) && (val != 0)) {
2521 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002522 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2523 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2524 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2525 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002526 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002527 err = voice_extn_compress_voip_open_input_stream(in);
2528 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002529 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002530 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002531 }
2532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 }
2534 }
2535
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002536 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2537 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002539 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 in->device = val;
2541 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002542 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002543 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 }
2545 }
2546
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002547done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002549 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550
2551 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302552error:
Eric Laurent994a6932013-07-17 11:51:42 -07002553 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 return ret;
2555}
2556
2557static char* in_get_parameters(const struct audio_stream *stream,
2558 const char *keys)
2559{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002560 struct stream_in *in = (struct stream_in *)stream;
2561 struct str_parms *query = str_parms_create_str(keys);
2562 char *str;
2563 char value[256];
2564 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002565
2566 if (!query || !reply) {
2567 ALOGE("in_get_parameters: failed to create query or reply");
2568 return NULL;
2569 }
2570
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002571 ALOGV("%s: enter: keys - %s", __func__, keys);
2572
2573 voice_extn_in_get_parameters(in, query, reply);
2574
2575 str = str_parms_to_str(reply);
2576 str_parms_destroy(query);
2577 str_parms_destroy(reply);
2578
2579 ALOGV("%s: exit: returns - %s", __func__, str);
2580 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581}
2582
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002583static int in_set_gain(struct audio_stream_in *stream __unused,
2584 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585{
2586 return 0;
2587}
2588
2589static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2590 size_t bytes)
2591{
2592 struct stream_in *in = (struct stream_in *)stream;
2593 struct audio_device *adev = in->dev;
2594 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302595 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302598
2599 if (in->pcm) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302600 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302601 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302602 ret= -EIO;;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302603 goto exit;
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002604 } else {
2605 if (in->is_st_session && !in->is_st_session_active) {
2606 ALOGD(" %s: Sound trigger is not active/SSR", __func__);
2607 ret= -EIO;;
2608 goto exit;
2609 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302610 }
2611 }
2612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 if (in->standby) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002614 if (!in->is_st_session) {
2615 pthread_mutex_lock(&adev->lock);
2616 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2617 ret = voice_extn_compress_voip_start_input_stream(in);
2618 else
2619 ret = start_input_stream(in);
2620 pthread_mutex_unlock(&adev->lock);
2621 if (ret != 0) {
2622 goto exit;
2623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 }
2625 in->standby = 0;
2626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627
2628 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002629 if (audio_extn_ssr_get_enabled() &&
2630 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002631 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002632 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2633 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002634 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2635 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002636 else
2637 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302638 if (ret < 0)
2639 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 }
2641
2642 /*
2643 * Instead of writing zeroes here, we could trust the hardware
2644 * to always provide zeroes when muted.
2645 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302646 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2647 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 memset(buffer, 0, bytes);
2649
2650exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302651 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302652 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302653 if (-ENETRESET == ret) {
Bharath Ramachandramurthy837535b2015-02-05 14:27:59 -08002654 /* CPE SSR results in kernel returning ENETRESET for sound trigger
2655 session reading on LAB data. In this case do not set sound card state
2656 offline, instead mark this sound trigger session inactive to avoid
2657 further reading of LAB data from CPE driver. Marking the session
2658 inactive handles both CPE and ADSP SSR for sound trigger session */
2659 if (!in->is_st_session)
2660 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2661 else
2662 in->is_st_session_active = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 pthread_mutex_unlock(&in->lock);
2665
2666 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302667 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302668 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302669 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302670 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302671 in->standby = true;
2672 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302673 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002675 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002676 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302677 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002678 }
2679 return bytes;
2680}
2681
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002682static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683{
2684 return 0;
2685}
2686
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002687static int add_remove_audio_effect(const struct audio_stream *stream,
2688 effect_handle_t effect,
2689 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002691 struct stream_in *in = (struct stream_in *)stream;
2692 int status = 0;
2693 effect_descriptor_t desc;
2694
2695 status = (*effect)->get_descriptor(effect, &desc);
2696 if (status != 0)
2697 return status;
2698
2699 pthread_mutex_lock(&in->lock);
2700 pthread_mutex_lock(&in->dev->lock);
2701 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2702 in->enable_aec != enable &&
2703 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2704 in->enable_aec = enable;
2705 if (!in->standby)
2706 select_devices(in->dev, in->usecase);
2707 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002708 if (in->enable_ns != enable &&
2709 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2710 in->enable_ns = enable;
2711 if (!in->standby)
2712 select_devices(in->dev, in->usecase);
2713 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002714 pthread_mutex_unlock(&in->dev->lock);
2715 pthread_mutex_unlock(&in->lock);
2716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 return 0;
2718}
2719
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002720static int in_add_audio_effect(const struct audio_stream *stream,
2721 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722{
Eric Laurent994a6932013-07-17 11:51:42 -07002723 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002724 return add_remove_audio_effect(stream, effect, true);
2725}
2726
2727static int in_remove_audio_effect(const struct audio_stream *stream,
2728 effect_handle_t effect)
2729{
Eric Laurent994a6932013-07-17 11:51:42 -07002730 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002731 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732}
2733
2734static int adev_open_output_stream(struct audio_hw_device *dev,
2735 audio_io_handle_t handle,
2736 audio_devices_t devices,
2737 audio_output_flags_t flags,
2738 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002739 struct audio_stream_out **stream_out,
2740 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741{
2742 struct audio_device *adev = (struct audio_device *)dev;
2743 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002744 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002745 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302748
2749 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2750 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2751 ALOGE(" sound card is not active rejecting compress output open request");
2752 return -EINVAL;
2753 }
2754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2756
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302757 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2758 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2759 devices, flags, &out->stream);
2760
2761
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002762 if (!out) {
2763 return -ENOMEM;
2764 }
2765
Haynes Mathew George204045b2015-02-25 20:32:03 -08002766 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2767 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 if (devices == AUDIO_DEVICE_NONE)
2770 devices = AUDIO_DEVICE_OUT_SPEAKER;
2771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 out->flags = flags;
2773 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002774 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002775 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 out->sample_rate = config->sample_rate;
2777 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2778 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002779 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002780 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002781 out->non_blocking = 0;
2782 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783
2784 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002785 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
2786 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2787 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2788
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002789 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002790 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2791 ret = read_hdmi_channel_masks(out);
2792
2793 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2794 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002795 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002796 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002797 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002798
2799 if (config->sample_rate == 0)
2800 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2801 if (config->channel_mask == 0)
2802 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2803
2804 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2807 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002809 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002811 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2812 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002813 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002814 ret = voice_extn_compress_voip_open_output_stream(out);
2815 if (ret != 0) {
2816 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2817 __func__, ret);
2818 goto error_open;
2819 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002820 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2821 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2822 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2823 ALOGE("%s: Unsupported Offload information", __func__);
2824 ret = -EINVAL;
2825 goto error_open;
2826 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002827
2828 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2829 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2830 ALOGV("read and update_pass through formats");
2831 ret = audio_extn_dolby_update_passt_formats(adev, out);
2832 if(ret != 0) {
2833 goto error_open;
2834 }
2835 if(config->offload_info.format == 0)
2836 config->offload_info.format = out->supported_formats[0];
2837 }
2838
Mingming Yin90310102013-11-13 16:57:00 -08002839 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002840 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 ALOGE("%s: Unsupported audio format", __func__);
2842 ret = -EINVAL;
2843 goto error_open;
2844 }
2845
2846 out->compr_config.codec = (struct snd_codec *)
2847 calloc(1, sizeof(struct snd_codec));
2848
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002849 if (!out->compr_config.codec) {
2850 ret = -ENOMEM;
2851 goto error_open;
2852 }
2853
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002854 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 if (config->offload_info.channel_mask)
2856 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002857 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002859 config->offload_info.channel_mask = config->channel_mask;
2860 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002861 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862 out->sample_rate = config->offload_info.sample_rate;
2863
2864 out->stream.set_callback = out_set_callback;
2865 out->stream.pause = out_pause;
2866 out->stream.resume = out_resume;
2867 out->stream.drain = out_drain;
2868 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002869 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002871 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002872 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002873 audio_extn_dolby_get_snd_codec_id(adev, out,
2874 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002875 else
2876 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002877 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002878 if (audio_is_offload_pcm(config->offload_info.format)) {
2879 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002880 platform_get_pcm_offload_buffer_size(&config->offload_info);
2881 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2882 out->compr_config.fragment_size =
2883 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002884 } else {
2885 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002886 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002887 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2889 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08002890 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 out->compr_config.codec->bit_rate =
2892 config->offload_info.bit_rate;
2893 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002894 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002896 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002897 /*TODO: Do we need to change it for passthrough */
2898 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899
Mingming Yin3ee55c62014-08-04 14:23:35 -07002900 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2901 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002902 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2903 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002904 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002905 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2906
Mingming Yin3ee55c62014-08-04 14:23:35 -07002907 if (out->bit_width == 24) {
2908 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2909 }
2910
Amit Shekhar6f461b12014-08-01 14:52:58 -07002911 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002912 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002913
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2915 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002916
Alexy Josephaa54c872014-12-03 02:46:47 -08002917 if (config->offload_info.use_small_bufs) {
2918 //this flag is set from framework only if its for PCM formats
2919 //no need to check for PCM format again
2920 out->non_blocking = 0;
2921 out->use_small_bufs = true;
2922 ALOGI("Keep write blocking for small buff: non_blockling %d",
2923 out->non_blocking);
2924 }
2925
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002926 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002927 out->offload_state = OFFLOAD_STATE_IDLE;
2928 out->playback_started = 0;
2929
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002930 audio_extn_dts_create_state_notifier_node(out->usecase);
2931
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002932 create_offload_callback_thread(out);
2933 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2934 __func__, config->offload_info.version,
2935 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002936 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002937 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002938 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2939 ret = voice_check_and_set_incall_music_usecase(adev, out);
2940 if (ret != 0) {
2941 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2942 __func__, ret);
2943 goto error_open;
2944 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002945 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2946 if (config->sample_rate == 0)
2947 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2948 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2949 config->sample_rate != 8000) {
2950 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2951 ret = -EINVAL;
2952 goto error_open;
2953 }
2954 out->sample_rate = config->sample_rate;
2955 out->config.rate = config->sample_rate;
2956 if (config->format == AUDIO_FORMAT_DEFAULT)
2957 config->format = AUDIO_FORMAT_PCM_16_BIT;
2958 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2959 config->format = AUDIO_FORMAT_PCM_16_BIT;
2960 ret = -EINVAL;
2961 goto error_open;
2962 }
2963 out->format = config->format;
2964 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2965 out->config = pcm_config_afe_proxy_playback;
2966 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002967 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002968 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2970 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002972 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2973 format = AUDIO_FORMAT_PCM_16_BIT;
2974 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2975 out->config = pcm_config_deep_buffer;
2976 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002977 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002978 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002979 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002980 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002981 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002982 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 }
2984
Amit Shekhar1d896042014-10-03 13:16:09 -07002985 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2986 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002987 /* TODO remove this hardcoding and check why width is zero*/
2988 if (out->bit_width == 0)
2989 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002990 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2991 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002992 devices, flags, format, out->sample_rate,
Amit Shekhar6f461b12014-08-01 14:52:58 -07002993 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002994 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2995 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2996 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002997 if(adev->primary_output == NULL)
2998 adev->primary_output = out;
2999 else {
3000 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003001 ret = -EEXIST;
3002 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003003 }
3004 }
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 /* Check if this usecase is already existing */
3007 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003008 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3009 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003012 ret = -EEXIST;
3013 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 }
3015 pthread_mutex_unlock(&adev->lock);
3016
3017 out->stream.common.get_sample_rate = out_get_sample_rate;
3018 out->stream.common.set_sample_rate = out_set_sample_rate;
3019 out->stream.common.get_buffer_size = out_get_buffer_size;
3020 out->stream.common.get_channels = out_get_channels;
3021 out->stream.common.get_format = out_get_format;
3022 out->stream.common.set_format = out_set_format;
3023 out->stream.common.standby = out_standby;
3024 out->stream.common.dump = out_dump;
3025 out->stream.common.set_parameters = out_set_parameters;
3026 out->stream.common.get_parameters = out_get_parameters;
3027 out->stream.common.add_audio_effect = out_add_audio_effect;
3028 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3029 out->stream.get_latency = out_get_latency;
3030 out->stream.set_volume = out_set_volume;
3031 out->stream.write = out_write;
3032 out->stream.get_render_position = out_get_render_position;
3033 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003034 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003037 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003038 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039
3040 config->format = out->stream.common.get_format(&out->stream.common);
3041 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3042 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3043
3044 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303045 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3046 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003047
3048 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3049 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3050 popcount(out->channel_mask), out->playback_started);
3051
Eric Laurent994a6932013-07-17 11:51:42 -07003052 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003054
3055error_open:
3056 free(out);
3057 *stream_out = NULL;
3058 ALOGD("%s: exit: ret %d", __func__, ret);
3059 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060}
3061
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003062static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 struct audio_stream_out *stream)
3064{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 struct stream_out *out = (struct stream_out *)stream;
3066 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003067 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303069 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3070
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003071 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303072 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003073 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303074 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 if(ret != 0)
3076 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3077 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003078 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 out_standby(&stream->common);
3080
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003081 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003082 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003083 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003084 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 if (out->compr_config.codec != NULL)
3086 free(out->compr_config.codec);
3087 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003088
3089 if (adev->voice_tx_output == out)
3090 adev->voice_tx_output = NULL;
3091
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 pthread_cond_destroy(&out->cond);
3093 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003094 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003095 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096}
3097
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003098static void close_compress_sessions(struct audio_device *adev)
3099{
Mingming Yin7b762e72015-03-04 13:47:32 -08003100 struct stream_out *out;
3101 struct listnode *node;
3102 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003103 pthread_mutex_lock(&adev->lock);
Mingming Yin7b762e72015-03-04 13:47:32 -08003104 list_for_each(node, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003105 usecase = node_to_item(node, struct audio_usecase, list);
Mingming Yin7b762e72015-03-04 13:47:32 -08003106 if (usecase && is_offload_usecase(usecase->id)) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003107 if (usecase && usecase->stream.out) {
3108 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3109 out = usecase->stream.out;
3110 pthread_mutex_unlock(&adev->lock);
3111 out_standby(&out->stream.common);
3112 pthread_mutex_lock(&adev->lock);
3113 }
3114 }
3115 }
3116 pthread_mutex_unlock(&adev->lock);
3117}
3118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003119static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3120{
3121 struct audio_device *adev = (struct audio_device *)dev;
3122 struct str_parms *parms;
3123 char *str;
3124 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003125 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003126 int ret;
3127 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003129 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303132 if (!parms)
3133 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003134 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3135 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303136 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303137 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303138 struct listnode *node;
3139 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303140 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303141 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003142 //close compress sessions on OFFLINE status
3143 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 } else if (strstr(snd_card_status, "ONLINE")) {
3145 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303146 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303147 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303148 }
3149
3150 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003151 status = voice_set_parameters(adev, parms);
3152 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003153 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003155 status = platform_set_parameters(adev->platform, parms);
3156 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003157 goto done;
3158
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003159 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3160 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003161 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3163 adev->bluetooth_nrec = true;
3164 else
3165 adev->bluetooth_nrec = false;
3166 }
3167
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003168 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3169 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3171 adev->screen_off = false;
3172 else
3173 adev->screen_off = true;
3174 }
3175
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003176 ret = str_parms_get_int(parms, "rotation", &val);
3177 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003178 bool reverse_speakers = false;
3179 switch(val) {
3180 // FIXME: note that the code below assumes that the speakers are in the correct placement
3181 // relative to the user when the device is rotated 90deg from its default rotation. This
3182 // assumption is device-specific, not platform-specific like this code.
3183 case 270:
3184 reverse_speakers = true;
3185 break;
3186 case 0:
3187 case 90:
3188 case 180:
3189 break;
3190 default:
3191 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003192 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003193 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003194 if (status == 0) {
3195 if (adev->speaker_lr_swap != reverse_speakers) {
3196 adev->speaker_lr_swap = reverse_speakers;
3197 // only update the selected device if there is active pcm playback
3198 struct audio_usecase *usecase;
3199 struct listnode *node;
3200 list_for_each(node, &adev->usecase_list) {
3201 usecase = node_to_item(node, struct audio_usecase, list);
3202 if (usecase->type == PCM_PLAYBACK) {
3203 select_devices(adev, usecase->id);
3204 break;
3205 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003206 }
3207 }
3208 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003209 }
3210
Mingming Yin514a8bc2014-07-29 15:22:21 -07003211 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3212 if (ret >= 0) {
3213 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3214 adev->bt_wb_speech_enabled = true;
3215 else
3216 adev->bt_wb_speech_enabled = false;
3217 }
3218
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003219 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3220 if (ret >= 0) {
3221 val = atoi(value);
3222 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3223 ALOGV("cache new edid");
3224 platform_cache_edid(adev->platform);
3225 }
3226 }
3227
3228 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3229 if (ret >= 0) {
3230 val = atoi(value);
3231 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3232 ALOGV("invalidate cached edid");
3233 platform_invalidate_edid(adev->platform);
3234 }
3235 }
3236
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003237 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003238
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003239done:
3240 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003241 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303242error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003243 ALOGV("%s: exit with code(%d)", __func__, status);
3244 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245}
3246
3247static char* adev_get_parameters(const struct audio_hw_device *dev,
3248 const char *keys)
3249{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003250 struct audio_device *adev = (struct audio_device *)dev;
3251 struct str_parms *reply = str_parms_create();
3252 struct str_parms *query = str_parms_create_str(keys);
3253 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303254 char value[256] = {0};
3255 int ret = 0;
3256
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003257 if (!query || !reply) {
3258 ALOGE("adev_get_parameters: failed to create query or reply");
3259 return NULL;
3260 }
3261
Naresh Tannirud7205b62014-06-20 02:54:48 +05303262 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3263 sizeof(value));
3264 if (ret >=0) {
3265 int val = 1;
3266 pthread_mutex_lock(&adev->snd_card_status.lock);
3267 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3268 val = 0;
3269 pthread_mutex_unlock(&adev->snd_card_status.lock);
3270 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3271 goto exit;
3272 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003273
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003274 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003275 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003276 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003277 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303278 pthread_mutex_unlock(&adev->lock);
3279
Naresh Tannirud7205b62014-06-20 02:54:48 +05303280exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003281 str = str_parms_to_str(reply);
3282 str_parms_destroy(query);
3283 str_parms_destroy(reply);
3284
3285 ALOGV("%s: exit: returns - %s", __func__, str);
3286 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287}
3288
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003289static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290{
3291 return 0;
3292}
3293
3294static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3295{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003296 int ret;
3297 struct audio_device *adev = (struct audio_device *)dev;
3298 pthread_mutex_lock(&adev->lock);
3299 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003300 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003301 pthread_mutex_unlock(&adev->lock);
3302 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303}
3304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003305static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3306 float volume __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_volume(struct audio_hw_device *dev __unused,
3312 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return -ENOSYS;
3315}
3316
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003317static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3318 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319{
3320 return -ENOSYS;
3321}
3322
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003323static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3324 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325{
3326 return -ENOSYS;
3327}
3328
3329static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3330{
3331 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 pthread_mutex_lock(&adev->lock);
3334 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003335 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003337 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3338 voice_is_in_call(adev)) {
3339 voice_stop_call(adev);
3340 adev->current_call_output = NULL;
3341 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 }
3343 pthread_mutex_unlock(&adev->lock);
3344 return 0;
3345}
3346
3347static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3348{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003349 int ret;
3350
3351 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003352 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003353 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3354 pthread_mutex_unlock(&adev->lock);
3355
3356 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357}
3358
3359static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3360{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003361 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 return 0;
3363}
3364
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003365static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 const struct audio_config *config)
3367{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003368 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003370 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3371 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372}
3373
3374static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003375 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 audio_devices_t devices,
3377 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003378 struct audio_stream_in **stream_in,
3379 audio_input_flags_t flags __unused,
3380 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003381 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382{
3383 struct audio_device *adev = (struct audio_device *)dev;
3384 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003385 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003386 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003387 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 *stream_in = NULL;
3390 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3391 return -EINVAL;
3392
3393 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003394
3395 if (!in) {
3396 ALOGE("failed to allocate input stream");
3397 return -ENOMEM;
3398 }
3399
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303400 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003401 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3402 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003404 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 in->stream.common.get_sample_rate = in_get_sample_rate;
3407 in->stream.common.set_sample_rate = in_set_sample_rate;
3408 in->stream.common.get_buffer_size = in_get_buffer_size;
3409 in->stream.common.get_channels = in_get_channels;
3410 in->stream.common.get_format = in_get_format;
3411 in->stream.common.set_format = in_set_format;
3412 in->stream.common.standby = in_standby;
3413 in->stream.common.dump = in_dump;
3414 in->stream.common.set_parameters = in_set_parameters;
3415 in->stream.common.get_parameters = in_get_parameters;
3416 in->stream.common.add_audio_effect = in_add_audio_effect;
3417 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3418 in->stream.set_gain = in_set_gain;
3419 in->stream.read = in_read;
3420 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3421
3422 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003423 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 in->standby = 1;
3426 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003427 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428
3429 /* Update config params with the requested sample rate and channels */
3430 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003431 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3432 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3433 is_low_latency = true;
3434#if LOW_LATENCY_CAPTURE_USE_CASE
3435 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3436#endif
3437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003440 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003441
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003442 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303443 if (adev->mode != AUDIO_MODE_IN_CALL) {
3444 ret = -EINVAL;
3445 goto err_open;
3446 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003447 if (config->sample_rate == 0)
3448 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3449 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3450 config->sample_rate != 8000) {
3451 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3452 ret = -EINVAL;
3453 goto err_open;
3454 }
3455 if (config->format == AUDIO_FORMAT_DEFAULT)
3456 config->format = AUDIO_FORMAT_PCM_16_BIT;
3457 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3458 config->format = AUDIO_FORMAT_PCM_16_BIT;
3459 ret = -EINVAL;
3460 goto err_open;
3461 }
3462
3463 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3464 in->config = pcm_config_afe_proxy_record;
3465 in->config.channels = channel_count;
3466 in->config.rate = config->sample_rate;
3467 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003468 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003469 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003470 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3471 ret = -EINVAL;
3472 goto err_open;
3473 }
3474 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003475 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003476 }
Mingming Yine62d7842013-10-25 16:26:03 -07003477 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003478 audio_extn_compr_cap_format_supported(config->format) &&
3479 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003480 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003481 } else {
3482 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003483 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003484 buffer_size = get_input_buffer_size(config->sample_rate,
3485 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003486 channel_count,
3487 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003488 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003489 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3490 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3491 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3492 (in->config.rate == 8000 || in->config.rate == 16000) &&
3493 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3494 voice_extn_compress_voip_open_input_stream(in);
3495 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003498 /* This stream could be for sound trigger lab,
3499 get sound trigger pcm if present */
3500 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303501 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003504 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003505 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506
3507err_open:
3508 free(in);
3509 *stream_in = NULL;
3510 return ret;
3511}
3512
3513static void adev_close_input_stream(struct audio_hw_device *dev,
3514 struct audio_stream_in *stream)
3515{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003516 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003517 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003518 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303519
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303520 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003521
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303522 /* Disable echo reference while closing input stream */
3523 platform_set_echo_reference(adev->platform, false);
3524
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003525 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303526 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003527 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303528 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003529 if (ret != 0)
3530 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3531 __func__, ret);
3532 } else
3533 in_standby(&stream->common);
3534
Mingming Yin7b762e72015-03-04 13:47:32 -08003535 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003536 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003537 audio_extn_ssr_deinit();
3538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
Mingming Yine62d7842013-10-25 16:26:03 -07003540 if(audio_extn_compr_cap_enabled() &&
3541 audio_extn_compr_cap_format_supported(in->config.format))
3542 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003543
3544 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 return;
3546}
3547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003548static int adev_dump(const audio_hw_device_t *device __unused,
3549 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550{
3551 return 0;
3552}
3553
3554static int adev_close(hw_device_t *device)
3555{
3556 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003557
3558 if (!adev)
3559 return 0;
3560
3561 pthread_mutex_lock(&adev_init_lock);
3562
3563 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003564 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003565 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003566 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003567 audio_route_free(adev->audio_route);
3568 free(adev->snd_dev_ref_cnt);
3569 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003570 free(device);
3571 adev = NULL;
3572 }
3573 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 return 0;
3575}
3576
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003577/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3578 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3579 * just that it _might_ work.
3580 */
3581static int period_size_is_plausible_for_low_latency(int period_size)
3582{
3583 switch (period_size) {
3584 case 160:
3585 case 240:
3586 case 320:
3587 case 480:
3588 return 1;
3589 default:
3590 return 0;
3591 }
3592}
3593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594static int adev_open(const hw_module_t *module, const char *name,
3595 hw_device_t **device)
3596{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003597 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003599 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3601
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003602 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003603 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003604 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003605 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003606 ALOGD("%s: returning existing instance of adev", __func__);
3607 ALOGD("%s: exit", __func__);
3608 pthread_mutex_unlock(&adev_init_lock);
3609 return 0;
3610 }
3611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 adev = calloc(1, sizeof(struct audio_device));
3613
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003614 if (!adev) {
3615 pthread_mutex_unlock(&adev_init_lock);
3616 return -ENOMEM;
3617 }
3618
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003619 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3622 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3623 adev->device.common.module = (struct hw_module_t *)module;
3624 adev->device.common.close = adev_close;
3625
3626 adev->device.init_check = adev_init_check;
3627 adev->device.set_voice_volume = adev_set_voice_volume;
3628 adev->device.set_master_volume = adev_set_master_volume;
3629 adev->device.get_master_volume = adev_get_master_volume;
3630 adev->device.set_master_mute = adev_set_master_mute;
3631 adev->device.get_master_mute = adev_get_master_mute;
3632 adev->device.set_mode = adev_set_mode;
3633 adev->device.set_mic_mute = adev_set_mic_mute;
3634 adev->device.get_mic_mute = adev_get_mic_mute;
3635 adev->device.set_parameters = adev_set_parameters;
3636 adev->device.get_parameters = adev_get_parameters;
3637 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3638 adev->device.open_output_stream = adev_open_output_stream;
3639 adev->device.close_output_stream = adev_close_output_stream;
3640 adev->device.open_input_stream = adev_open_input_stream;
3641 adev->device.close_input_stream = adev_close_input_stream;
3642 adev->device.dump = adev_dump;
3643
3644 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003646 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003647 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003650 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003651 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003652 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003653 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003654 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003655 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003656 adev->offload_usecases_state = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303657
3658 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3659 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003661 adev->platform = platform_init(adev);
3662 if (!adev->platform) {
3663 free(adev->snd_dev_ref_cnt);
3664 free(adev);
3665 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3666 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003667 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003668 return -EINVAL;
3669 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003670
Naresh Tanniru4c630392014-05-12 01:05:52 +05303671 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3672
Eric Laurentc4aef752013-09-12 17:45:53 -07003673 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3674 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3675 if (adev->visualizer_lib == NULL) {
3676 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3677 } else {
3678 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3679 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003680 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003681 "visualizer_hal_start_output");
3682 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003683 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003684 "visualizer_hal_stop_output");
3685 }
3686 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003687 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003688 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003689
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003690 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3691 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3692 if (adev->offload_effects_lib == NULL) {
3693 ALOGE("%s: DLOPEN failed for %s", __func__,
3694 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3695 } else {
3696 ALOGV("%s: DLOPEN successful for %s", __func__,
3697 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3698 adev->offload_effects_start_output =
3699 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3700 "offload_effects_bundle_hal_start_output");
3701 adev->offload_effects_stop_output =
3702 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3703 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003704 adev->offload_effects_set_hpx_state =
3705 (int (*)(bool))dlsym(adev->offload_effects_lib,
3706 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003707 }
3708 }
3709
Mingming Yin514a8bc2014-07-29 15:22:21 -07003710 adev->bt_wb_speech_enabled = false;
3711
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003712 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 *device = &adev->device.common;
3714
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003715 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3716 &adev->streams_output_cfg_list);
3717
Kiran Kandi910e1862013-10-29 13:29:42 -07003718 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003719
3720 char value[PROPERTY_VALUE_MAX];
3721 int trial;
3722 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3723 trial = atoi(value);
3724 if (period_size_is_plausible_for_low_latency(trial)) {
3725 pcm_config_low_latency.period_size = trial;
3726 pcm_config_low_latency.start_threshold = trial / 4;
3727 pcm_config_low_latency.avail_min = trial / 4;
3728 configured_low_latency_capture_period_size = trial;
3729 }
3730 }
3731 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3732 trial = atoi(value);
3733 if (period_size_is_plausible_for_low_latency(trial)) {
3734 configured_low_latency_capture_period_size = trial;
3735 }
3736 }
3737
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003738 pthread_mutex_unlock(&adev_init_lock);
3739
Eric Laurent994a6932013-07-17 11:51:42 -07003740 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 return 0;
3742}
3743
3744static struct hw_module_methods_t hal_module_methods = {
3745 .open = adev_open,
3746};
3747
3748struct audio_module HAL_MODULE_INFO_SYM = {
3749 .common = {
3750 .tag = HARDWARE_MODULE_TAG,
3751 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3752 .hal_api_version = HARDWARE_HAL_API_VERSION,
3753 .id = AUDIO_HARDWARE_MODULE_ID,
3754 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003755 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 .methods = &hal_module_methods,
3757 },
3758};