blob: e64d318f7bbdde12ddb457bfb7946715d80a7fc5 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530424 platform_add_backend_name(mixer_path, snd_device, usecase);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530446 platform_add_backend_name(mixer_path, snd_device, usecase);
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
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530490 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800491 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700492 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700493 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
494 adev->snd_dev_ref_cnt[snd_device]--;
495 return -EINVAL;
496 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200497 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800498 if (audio_extn_spkr_prot_start_processing(snd_device)) {
499 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200500 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800501 return -EINVAL;
502 }
503 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700504 ALOGV("%s: snd_device(%d: %s)", __func__,
505 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700506 /* due to the possibility of calibration overwrite between listen
507 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700508 audio_extn_sound_trigger_update_device_status(snd_device,
509 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530510 audio_extn_listen_update_device_status(snd_device,
511 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700512 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700513 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700514 audio_extn_sound_trigger_update_device_status(snd_device,
515 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530516 audio_extn_listen_update_device_status(snd_device,
517 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700518 return -EINVAL;
519 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300520 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700521 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523 return 0;
524}
525
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700526int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700527 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800528{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700529 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
530
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800531 if (snd_device < SND_DEVICE_MIN ||
532 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800533 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800534 return -EINVAL;
535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700536 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
537 ALOGE("%s: device ref cnt is already 0", __func__);
538 return -EINVAL;
539 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700540
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700542
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700543 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
544 ALOGE("%s: Invalid sound device returned", __func__);
545 return -EINVAL;
546 }
547
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700548 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700549 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700550 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800551 /* exit usb play back thread */
552 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
553 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
554 audio_extn_usb_stop_playback();
555
556 /* exit usb capture thread */
557 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700558 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800559
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530560 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +0530561 snd_device == SND_DEVICE_OUT_SPEAKER_VBAT || snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800562 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700563 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700564 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700566 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300567 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700568
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530569 if (snd_device == SND_DEVICE_OUT_HDMI)
570 adev->mChannelStatusSet = false;
571
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200572 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700573 audio_extn_sound_trigger_update_device_status(snd_device,
574 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530575 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800576 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 return 0;
580}
581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582static void check_usecases_codec_backend(struct audio_device *adev,
583 struct audio_usecase *uc_info,
584 snd_device_t snd_device)
585{
586 struct listnode *node;
587 struct audio_usecase *usecase;
588 bool switch_device[AUDIO_USECASE_MAX];
589 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530590 int backend_idx = DEFAULT_CODEC_BACKEND;
591 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700592
593 /*
594 * This function is to make sure that all the usecases that are active on
595 * the hardware codec backend are always routed to any one device that is
596 * handled by the hardware codec.
597 * For example, if low-latency and deep-buffer usecases are currently active
598 * on speaker and out_set_parameters(headset) is received on low-latency
599 * output, then we have to make sure deep-buffer is also switched to headset,
600 * because of the limitation that both the devices cannot be enabled
601 * at the same time as they share the same backend.
602 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700603 /*
604 * This call is to check if we need to force routing for a particular stream
605 * If there is a backend configuration change for the device when a
606 * new stream starts, then ADM needs to be closed and re-opened with the new
607 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530608 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700609 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530610 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
611 snd_device);
612 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800614 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800615 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 for (i = 0; i < AUDIO_USECASE_MAX; i++)
617 switch_device[i] = false;
618
619 list_for_each(node, &adev->usecase_list) {
620 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530621
622 if (usecase == uc_info)
623 continue;
624 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
625 ALOGV("%s: backend_idx: %d,"
626 "usecase_backend_idx: %d, curr device: %s, usecase device:"
627 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530628 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530629
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800630 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700631 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530632 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
633 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530634 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530635 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700636 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700637 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700638 switch_device[usecase->id] = true;
639 num_uc_to_switch++;
640 }
641 }
642
643 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700644 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530646 /* Make sure the previous devices to be disabled first and then enable the
647 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 list_for_each(node, &adev->usecase_list) {
649 usecase = node_to_item(node, struct audio_usecase, list);
650 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700651 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700652 }
653 }
654
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700655 list_for_each(node, &adev->usecase_list) {
656 usecase = node_to_item(node, struct audio_usecase, list);
657 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700658 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700659 }
660 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700661
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662 /* Re-route all the usecases on the shared backend other than the
663 specified usecase to new snd devices */
664 list_for_each(node, &adev->usecase_list) {
665 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530666 /* Update the out_snd_device only for the usecases that are enabled here */
667 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
668 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530669 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672 }
673}
674
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700675static void check_and_route_capture_usecases(struct audio_device *adev,
676 struct audio_usecase *uc_info,
677 snd_device_t snd_device)
678{
679 struct listnode *node;
680 struct audio_usecase *usecase;
681 bool switch_device[AUDIO_USECASE_MAX];
682 int i, num_uc_to_switch = 0;
683
684 /*
685 * This function is to make sure that all the active capture usecases
686 * are always routed to the same input sound device.
687 * For example, if audio-record and voice-call usecases are currently
688 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
689 * is received for voice call then we have to make sure that audio-record
690 * usecase is also switched to earpiece i.e. voice-dmic-ef,
691 * because of the limitation that two devices cannot be enabled
692 * at the same time if they share the same backend.
693 */
694 for (i = 0; i < AUDIO_USECASE_MAX; i++)
695 switch_device[i] = false;
696
697 list_for_each(node, &adev->usecase_list) {
698 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800699 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700700 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700701 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700702 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
703 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700704 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700705 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
706 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700707 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700708 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700709 switch_device[usecase->id] = true;
710 num_uc_to_switch++;
711 }
712 }
713
714 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700715 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700716
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530717 /* Make sure the previous devices to be disabled first and then enable the
718 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700719 list_for_each(node, &adev->usecase_list) {
720 usecase = node_to_item(node, struct audio_usecase, list);
721 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700722 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800723 }
724 }
725
726 list_for_each(node, &adev->usecase_list) {
727 usecase = node_to_item(node, struct audio_usecase, list);
728 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700729 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700730 }
731 }
732
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700733 /* Re-route all the usecases on the shared backend other than the
734 specified usecase to new snd devices */
735 list_for_each(node, &adev->usecase_list) {
736 usecase = node_to_item(node, struct audio_usecase, list);
737 /* Update the in_snd_device only before enabling the audio route */
738 if (switch_device[usecase->id] ) {
739 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800740 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530741 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 }
743 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700744 }
745}
746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700748static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800749{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700750 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700751 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752
753 switch (channels) {
754 /*
755 * Do not handle stereo output in Multi-channel cases
756 * Stereo case is handled in normal playback path
757 */
758 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700759 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
760 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
761 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
763 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765 break;
766 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700767 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
769 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
773 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774 break;
775 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700776 ALOGE("HDMI does not support multi channel playback");
777 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800778 break;
779 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700780 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800781}
782
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800783audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
784 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700785{
786 struct audio_usecase *usecase;
787 struct listnode *node;
788
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800791 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700792 ALOGV("%s: usecase id %d", __func__, usecase->id);
793 return usecase->id;
794 }
795 }
796 return USECASE_INVALID;
797}
798
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700799struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700800 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700801{
802 struct audio_usecase *usecase;
803 struct listnode *node;
804
805 list_for_each(node, &adev->usecase_list) {
806 usecase = node_to_item(node, struct audio_usecase, list);
807 if (usecase->id == uc_id)
808 return usecase;
809 }
810 return NULL;
811}
812
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700813int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800815 snd_device_t out_snd_device = SND_DEVICE_NONE;
816 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 struct audio_usecase *usecase = NULL;
818 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800819 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800820 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800821 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800822 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 usecase = get_usecase_from_list(adev, uc_id);
826 if (usecase == NULL) {
827 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
828 return -EINVAL;
829 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800831 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800832 (usecase->type == VOIP_CALL) ||
833 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700834 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800835 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700836 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 usecase->devices = usecase->stream.out->devices;
838 } else {
839 /*
840 * If the voice call is active, use the sound devices of voice call usecase
841 * so that it would not result any device switch. All the usecases will
842 * be switched to new device when select_devices() is called for voice call
843 * usecase. This is to avoid switching devices for voice call when
844 * check_usecases_codec_backend() is called below.
845 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700846 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800848 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700849 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
850 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 in_snd_device = vc_usecase->in_snd_device;
852 out_snd_device = vc_usecase->out_snd_device;
853 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800854 } else if (voice_extn_compress_voip_is_active(adev)) {
855 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700856 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530857 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700858 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800859 in_snd_device = voip_usecase->in_snd_device;
860 out_snd_device = voip_usecase->out_snd_device;
861 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800862 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800863 hfp_ucid = audio_extn_hfp_get_usecase();
864 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700865 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800866 in_snd_device = hfp_usecase->in_snd_device;
867 out_snd_device = hfp_usecase->out_snd_device;
868 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700869 }
870 if (usecase->type == PCM_PLAYBACK) {
871 usecase->devices = usecase->stream.out->devices;
872 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700873 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700874 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800875 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700876 if (usecase->stream.out == adev->primary_output &&
877 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800878 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700879 select_devices(adev, adev->active_input->usecase);
880 }
881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 } else if (usecase->type == PCM_CAPTURE) {
883 usecase->devices = usecase->stream.in->device;
884 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700885 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700886 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530887 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
888 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
889 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
890 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800892 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700893 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
894 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700895 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700896 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700897 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
900
901 if (out_snd_device == usecase->out_snd_device &&
902 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800903 return 0;
904 }
905
sangwoobc677242013-08-08 16:53:43 +0900906 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700907 out_snd_device, platform_get_snd_device_name(out_snd_device),
908 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800910 /*
911 * Limitation: While in call, to do a device switch we need to disable
912 * and enable both RX and TX devices though one of them is same as current
913 * device.
914 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700915 if ((usecase->type == VOICE_CALL) &&
916 (usecase->in_snd_device != SND_DEVICE_NONE) &&
917 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700918 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700919 /* Disable sidetone only if voice call already exists */
920 if (voice_is_call_state_active(adev))
921 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800922 }
923
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700924 /* Disable current sound devices */
925 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700926 disable_audio_route(adev, usecase);
927 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800928 }
929
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700930 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700931 disable_audio_route(adev, usecase);
932 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800933 }
934
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800935 /* Applicable only on the targets that has external modem.
936 * New device information should be sent to modem before enabling
937 * the devices to reduce in-call device switch time.
938 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700939 if ((usecase->type == VOICE_CALL) &&
940 (usecase->in_snd_device != SND_DEVICE_NONE) &&
941 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800942 status = platform_switch_voice_call_enable_device_config(adev->platform,
943 out_snd_device,
944 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700945 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800946
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 /* Enable new sound devices */
948 if (out_snd_device != SND_DEVICE_NONE) {
949 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
950 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700951 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 }
953
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700954 if (in_snd_device != SND_DEVICE_NONE) {
955 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700956 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958
Avinash Vaish71a8b972014-07-24 15:36:33 +0530959 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700960 status = platform_switch_voice_call_device_post(adev->platform,
961 out_snd_device,
962 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530963 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700964 /* Enable sidetone only if voice call already exists */
965 if (voice_is_call_state_active(adev))
966 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530967 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800968
sangwoo170731f2013-06-08 15:36:36 +0900969 usecase->in_snd_device = in_snd_device;
970 usecase->out_snd_device = out_snd_device;
971
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530972 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700973 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530974 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700975 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530976 usecase->stream.out->flags,
977 usecase->stream.out->format,
978 usecase->stream.out->sample_rate,
979 usecase->stream.out->bit_width,
980 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700981 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530982 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700983
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700984 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900985
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800986 /* Applicable only on the targets that has external modem.
987 * Enable device command should be sent to modem only after
988 * enabling voice call mixer controls
989 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700990 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800991 status = platform_switch_voice_call_usecase_route_post(adev->platform,
992 out_snd_device,
993 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530994 ALOGD("%s: done",__func__);
995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996 return status;
997}
998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999static int stop_input_stream(struct stream_in *in)
1000{
1001 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002 struct audio_usecase *uc_info;
1003 struct audio_device *adev = in->dev;
1004
Eric Laurentc8400632013-02-14 19:04:54 -08001005 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006
Eric Laurent994a6932013-07-17 11:51:42 -07001007 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001008 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001009 uc_info = get_usecase_from_list(adev, in->usecase);
1010 if (uc_info == NULL) {
1011 ALOGE("%s: Could not find the usecase (%d) in the list",
1012 __func__, in->usecase);
1013 return -EINVAL;
1014 }
1015
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001016 /* Close in-call recording streams */
1017 voice_check_and_stop_incall_rec_usecase(adev, in);
1018
Eric Laurent150dbfe2013-02-27 14:31:02 -08001019 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001020 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001021
1022 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001023 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001025 list_remove(&uc_info->list);
1026 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027
Eric Laurent994a6932013-07-17 11:51:42 -07001028 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 return ret;
1030}
1031
1032int start_input_stream(struct stream_in *in)
1033{
1034 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001035 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 struct audio_usecase *uc_info;
1037 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301038 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301040 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1041 if (get_usecase_from_list(adev, usecase) == NULL)
1042 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301043 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1044 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001045
Naresh Tanniru80659832014-06-04 18:17:56 +05301046
1047 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301048 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301049 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301050 goto error_config;
1051 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301052
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001053 /* Check if source matches incall recording usecase criteria */
1054 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1055 if (ret)
1056 goto error_config;
1057 else
Yamit Mehtaaafda4b2015-07-13 12:51:33 +05301058 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1059
1060 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1061 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1062 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1063 goto error_config;
1064 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001065
Eric Laurentb23d5282013-05-14 15:27:20 -07001066 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 if (in->pcm_device_id < 0) {
1068 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1069 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001070 ret = -EINVAL;
1071 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001073
1074 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001076
1077 if (!uc_info) {
1078 ret = -ENOMEM;
1079 goto error_config;
1080 }
1081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 uc_info->id = in->usecase;
1083 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001084 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 uc_info->devices = in->device;
1086 uc_info->in_snd_device = SND_DEVICE_NONE;
1087 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001088
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001089 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301090 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001092
Eric Laurentc8400632013-02-14 19:04:54 -08001093 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001094 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1095
1096 unsigned int flags = PCM_IN;
1097 unsigned int pcm_open_retry_count = 0;
1098
1099 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1100 flags |= PCM_MMAP | PCM_NOIRQ;
1101 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1102 }
1103
1104 while (1) {
1105 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1106 flags, &in->config);
1107 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1108 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1109 if (in->pcm != NULL) {
1110 pcm_close(in->pcm);
1111 in->pcm = NULL;
1112 }
1113 if (pcm_open_retry_count-- == 0) {
1114 ret = -EIO;
1115 goto error_open;
1116 }
1117 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1118 continue;
1119 }
1120 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301122 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301123
Eric Laurent994a6932013-07-17 11:51:42 -07001124 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001125 return ret;
1126
1127error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301129 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001130
1131error_config:
1132 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001134
1135 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136}
1137
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001138/* must be called with out->lock locked */
1139static int send_offload_cmd_l(struct stream_out* out, int command)
1140{
1141 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1142
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001143 if (!cmd) {
1144 ALOGE("failed to allocate mem for command 0x%x", command);
1145 return -ENOMEM;
1146 }
1147
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001148 ALOGVV("%s %d", __func__, command);
1149
1150 cmd->cmd = command;
1151 list_add_tail(&out->offload_cmd_list, &cmd->node);
1152 pthread_cond_signal(&out->offload_cond);
1153 return 0;
1154}
1155
1156/* must be called iwth out->lock locked */
1157static void stop_compressed_output_l(struct stream_out *out)
1158{
1159 out->offload_state = OFFLOAD_STATE_IDLE;
1160 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001161 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001162 if (out->compr != NULL) {
1163 compress_stop(out->compr);
1164 while (out->offload_thread_blocked) {
1165 pthread_cond_wait(&out->cond, &out->lock);
1166 }
1167 }
1168}
1169
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001170bool is_offload_usecase(audio_usecase_t uc_id)
1171{
1172 unsigned int i;
1173 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1174 if (uc_id == offload_usecases[i])
1175 return true;
1176 }
1177 return false;
1178}
1179
1180static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1181{
1182 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1183 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1184 char value[PROPERTY_VALUE_MAX] = {0};
1185
1186 property_get("audio.offload.multiple.enabled", value, NULL);
1187 if (!(atoi(value) || !strncmp("true", value, 4)))
1188 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1189
1190 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1191 for (i = 0; i < num_usecase; i++) {
1192 if (!(adev->offload_usecases_state & (0x1<<i))) {
1193 adev->offload_usecases_state |= 0x1 << i;
1194 ret = offload_usecases[i];
1195 break;
1196 }
1197 }
1198 ALOGV("%s: offload usecase is %d", __func__, ret);
1199 return ret;
1200}
1201
1202static void free_offload_usecase(struct audio_device *adev,
1203 audio_usecase_t uc_id)
1204{
1205 unsigned int i;
1206 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1207 if (offload_usecases[i] == uc_id) {
1208 adev->offload_usecases_state &= ~(0x1<<i);
1209 break;
1210 }
1211 }
1212 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1213}
1214
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215static void *offload_thread_loop(void *context)
1216{
1217 struct stream_out *out = (struct stream_out *) context;
1218 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001219 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001220
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001221 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1222 set_sched_policy(0, SP_FOREGROUND);
1223 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1224
1225 ALOGV("%s", __func__);
1226 pthread_mutex_lock(&out->lock);
1227 for (;;) {
1228 struct offload_cmd *cmd = NULL;
1229 stream_callback_event_t event;
1230 bool send_callback = false;
1231
1232 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1233 __func__, list_empty(&out->offload_cmd_list),
1234 out->offload_state);
1235 if (list_empty(&out->offload_cmd_list)) {
1236 ALOGV("%s SLEEPING", __func__);
1237 pthread_cond_wait(&out->offload_cond, &out->lock);
1238 ALOGV("%s RUNNING", __func__);
1239 continue;
1240 }
1241
1242 item = list_head(&out->offload_cmd_list);
1243 cmd = node_to_item(item, struct offload_cmd, node);
1244 list_remove(item);
1245
1246 ALOGVV("%s STATE %d CMD %d out->compr %p",
1247 __func__, out->offload_state, cmd->cmd, out->compr);
1248
1249 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1250 free(cmd);
1251 break;
1252 }
1253
1254 if (out->compr == NULL) {
1255 ALOGE("%s: Compress handle is NULL", __func__);
1256 pthread_cond_signal(&out->cond);
1257 continue;
1258 }
1259 out->offload_thread_blocked = true;
1260 pthread_mutex_unlock(&out->lock);
1261 send_callback = false;
1262 switch(cmd->cmd) {
1263 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001264 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001265 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001266 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001267 send_callback = true;
1268 event = STREAM_CBK_EVENT_WRITE_READY;
1269 break;
1270 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001271 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301272 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001273 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301274 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001275 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301276 if (ret < 0)
1277 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301278 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301279 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001280 compress_drain(out->compr);
1281 else
1282 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301283 if (ret != -ENETRESET) {
1284 send_callback = true;
1285 event = STREAM_CBK_EVENT_DRAIN_READY;
1286 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1287 } else
1288 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 break;
1290 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001291 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001292 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001293 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001294 send_callback = true;
1295 event = STREAM_CBK_EVENT_DRAIN_READY;
1296 break;
1297 default:
1298 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1299 break;
1300 }
1301 pthread_mutex_lock(&out->lock);
1302 out->offload_thread_blocked = false;
1303 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001304 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001305 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001307 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001308 free(cmd);
1309 }
1310
1311 pthread_cond_signal(&out->cond);
1312 while (!list_empty(&out->offload_cmd_list)) {
1313 item = list_head(&out->offload_cmd_list);
1314 list_remove(item);
1315 free(node_to_item(item, struct offload_cmd, node));
1316 }
1317 pthread_mutex_unlock(&out->lock);
1318
1319 return NULL;
1320}
1321
1322static int create_offload_callback_thread(struct stream_out *out)
1323{
1324 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1325 list_init(&out->offload_cmd_list);
1326 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1327 offload_thread_loop, out);
1328 return 0;
1329}
1330
1331static int destroy_offload_callback_thread(struct stream_out *out)
1332{
1333 pthread_mutex_lock(&out->lock);
1334 stop_compressed_output_l(out);
1335 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1336
1337 pthread_mutex_unlock(&out->lock);
1338 pthread_join(out->offload_thread, (void **) NULL);
1339 pthread_cond_destroy(&out->offload_cond);
1340
1341 return 0;
1342}
1343
Eric Laurent07eeafd2013-10-06 12:52:49 -07001344static bool allow_hdmi_channel_config(struct audio_device *adev)
1345{
1346 struct listnode *node;
1347 struct audio_usecase *usecase;
1348 bool ret = true;
1349
1350 list_for_each(node, &adev->usecase_list) {
1351 usecase = node_to_item(node, struct audio_usecase, list);
1352 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1353 /*
1354 * If voice call is already existing, do not proceed further to avoid
1355 * disabling/enabling both RX and TX devices, CSD calls, etc.
1356 * Once the voice call done, the HDMI channels can be configured to
1357 * max channels of remaining use cases.
1358 */
1359 if (usecase->id == USECASE_VOICE_CALL) {
1360 ALOGD("%s: voice call is active, no change in HDMI channels",
1361 __func__);
1362 ret = false;
1363 break;
1364 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1365 ALOGD("%s: multi channel playback is active, "
1366 "no change in HDMI channels", __func__);
1367 ret = false;
1368 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001369 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001370 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001371 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1372 ", no change in HDMI channels", __func__,
1373 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001374 ret = false;
1375 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001376 }
1377 }
1378 }
1379 return ret;
1380}
1381
1382static int check_and_set_hdmi_channels(struct audio_device *adev,
1383 unsigned int channels)
1384{
1385 struct listnode *node;
1386 struct audio_usecase *usecase;
1387
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001388 unsigned int supported_channels = platform_edid_get_max_channels(
1389 adev->platform);
1390 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001391 /* Check if change in HDMI channel config is allowed */
1392 if (!allow_hdmi_channel_config(adev))
1393 return 0;
1394
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001395 if (channels > supported_channels)
1396 channels = supported_channels;
1397
Eric Laurent07eeafd2013-10-06 12:52:49 -07001398 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001399 ALOGD("%s: Requested channels are same as current channels(%d)",
1400 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001401 return 0;
1402 }
1403
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001404 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001405 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001406 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001407 adev->cur_hdmi_channels = channels;
1408
1409 /*
1410 * Deroute all the playback streams routed to HDMI so that
1411 * the back end is deactivated. Note that backend will not
1412 * be deactivated if any one stream is connected to it.
1413 */
1414 list_for_each(node, &adev->usecase_list) {
1415 usecase = node_to_item(node, struct audio_usecase, list);
1416 if (usecase->type == PCM_PLAYBACK &&
1417 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001418 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001419 }
1420 }
1421
1422 /*
1423 * Enable all the streams disabled above. Now the HDMI backend
1424 * will be activated with new channel configuration
1425 */
1426 list_for_each(node, &adev->usecase_list) {
1427 usecase = node_to_item(node, struct audio_usecase, list);
1428 if (usecase->type == PCM_PLAYBACK &&
1429 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001430 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001431 }
1432 }
1433
1434 return 0;
1435}
1436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437static int stop_output_stream(struct stream_out *out)
1438{
1439 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 struct audio_usecase *uc_info;
1441 struct audio_device *adev = out->dev;
1442
Eric Laurent994a6932013-07-17 11:51:42 -07001443 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445 uc_info = get_usecase_from_list(adev, out->usecase);
1446 if (uc_info == NULL) {
1447 ALOGE("%s: Could not find the usecase (%d) in the list",
1448 __func__, out->usecase);
1449 return -EINVAL;
1450 }
1451
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001452 if (is_offload_usecase(out->usecase) &&
1453 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001454 if (adev->visualizer_stop_output != NULL)
1455 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001456
1457 audio_extn_dts_remove_state_notifier_node(out->usecase);
1458
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001459 if (adev->offload_effects_stop_output != NULL)
1460 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1461 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001462
Eric Laurent150dbfe2013-02-27 14:31:02 -08001463 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001464 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465
1466 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001467 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001468
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001469 list_remove(&uc_info->list);
1470 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001472 if (is_offload_usecase(out->usecase) &&
1473 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1474 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1475 ALOGV("Disable passthrough , reset mixer to pcm");
1476 /* NO_PASSTHROUGH */
1477 out->compr_config.codec->compr_passthr = 0;
1478 audio_extn_dolby_set_hdmi_config(adev, out);
1479 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1480 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001481 /* Must be called after removing the usecase from list */
1482 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1483 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1484
Eric Laurent994a6932013-07-17 11:51:42 -07001485 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 return ret;
1487}
1488
1489int start_output_stream(struct stream_out *out)
1490{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001492 int sink_channels = 0;
1493 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 struct audio_usecase *uc_info;
1495 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301496 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001498 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1499 ret = -EINVAL;
1500 goto error_config;
1501 }
1502
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301503 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1504 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1505 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301506
Naresh Tanniru80659832014-06-04 18:17:56 +05301507 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301508 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301509 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301510 goto error_config;
1511 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301512
Eric Laurentb23d5282013-05-14 15:27:20 -07001513 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 if (out->pcm_device_id < 0) {
1515 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1516 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001517 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001518 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 }
1520
1521 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001522
1523 if (!uc_info) {
1524 ret = -ENOMEM;
1525 goto error_config;
1526 }
1527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 uc_info->id = out->usecase;
1529 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001530 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531 uc_info->devices = out->devices;
1532 uc_info->in_snd_device = SND_DEVICE_NONE;
1533 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001534 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001535 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001536 if (is_offload_usecase(out->usecase)) {
1537 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001538 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1539 }
1540 }
Mingming Yin9c041392014-05-01 15:37:31 -07001541 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1542 if (!strncmp("true", prop_value, 4)) {
1543 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001544 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1545 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001546 check_and_set_hdmi_channels(adev, sink_channels);
1547 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001548 if (is_offload_usecase(out->usecase)) {
1549 unsigned int ch_count = out->compr_config.codec->ch_in;
1550 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1551 /* backend channel config for passthrough stream is stereo */
1552 ch_count = 2;
1553 check_and_set_hdmi_channels(adev, ch_count);
1554 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001555 check_and_set_hdmi_channels(adev, out->config.channels);
1556 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001557 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001558 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001559 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001560
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 select_devices(adev, out->usecase);
1562
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001563 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1564 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001565 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001566 unsigned int flags = PCM_OUT;
1567 unsigned int pcm_open_retry_count = 0;
1568 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1569 flags |= PCM_MMAP | PCM_NOIRQ;
1570 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1571 } else
1572 flags |= PCM_MONOTONIC;
1573
1574 while (1) {
1575 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1576 flags, &out->config);
1577 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1578 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1579 if (out->pcm != NULL) {
1580 pcm_close(out->pcm);
1581 out->pcm = NULL;
1582 }
1583 if (pcm_open_retry_count-- == 0) {
1584 ret = -EIO;
1585 goto error_open;
1586 }
1587 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1588 continue;
1589 }
1590 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001592 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1593 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001594 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001595 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1596 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001598 out->compr = compress_open(adev->snd_card,
1599 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001600 COMPRESS_IN, &out->compr_config);
1601 if (out->compr && !is_compress_ready(out->compr)) {
1602 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1603 compress_close(out->compr);
1604 out->compr = NULL;
1605 ret = -EIO;
1606 goto error_open;
1607 }
1608 if (out->offload_callback)
1609 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001610
Fred Oh3f43e742015-03-04 18:42:34 -08001611 /* Since small bufs uses blocking writes, a write will be blocked
1612 for the default max poll time (20s) in the event of an SSR.
1613 Reduce the poll time to observe and deal with SSR faster.
1614 */
1615 if (out->use_small_bufs) {
1616 compress_set_max_poll_wait(out->compr, 1000);
1617 }
1618
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001619 audio_extn_dts_create_state_notifier_node(out->usecase);
1620 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1621 popcount(out->channel_mask),
1622 out->playback_started);
1623
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001624#ifdef DS1_DOLBY_DDP_ENABLED
1625 if (audio_extn_is_dolby_format(out->format))
1626 audio_extn_dolby_send_ddp_endp_params(adev);
1627#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001628 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1629 if (adev->visualizer_start_output != NULL)
1630 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1631 if (adev->offload_effects_start_output != NULL)
1632 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001633 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 }
Eric Laurent994a6932013-07-17 11:51:42 -07001636 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001638error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001640error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001641 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642}
1643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644static int check_input_parameters(uint32_t sample_rate,
1645 audio_format_t format,
1646 int channel_count)
1647{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001648 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001650 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001651 !voice_extn_compress_voip_is_format_supported(format) &&
1652 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001653
1654 switch (channel_count) {
1655 case 1:
1656 case 2:
1657 case 6:
1658 break;
1659 default:
1660 ret = -EINVAL;
1661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662
1663 switch (sample_rate) {
1664 case 8000:
1665 case 11025:
1666 case 12000:
1667 case 16000:
1668 case 22050:
1669 case 24000:
1670 case 32000:
1671 case 44100:
1672 case 48000:
1673 break;
1674 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001675 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 }
1677
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001678 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679}
1680
1681static size_t get_input_buffer_size(uint32_t sample_rate,
1682 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001683 int channel_count,
1684 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685{
1686 size_t size = 0;
1687
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001688 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1689 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001691 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001692 if (is_low_latency)
1693 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001694 /* ToDo: should use frame_size computed based on the format and
1695 channel_count here. */
1696 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001698 /* make sure the size is multiple of 32 bytes
1699 * At 48 kHz mono 16-bit PCM:
1700 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1701 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1702 */
1703 size += 0x1f;
1704 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001705
1706 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707}
1708
1709static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1710{
1711 struct stream_out *out = (struct stream_out *)stream;
1712
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714}
1715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001716static int out_set_sample_rate(struct audio_stream *stream __unused,
1717 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718{
1719 return -ENOSYS;
1720}
1721
1722static size_t out_get_buffer_size(const struct audio_stream *stream)
1723{
1724 struct stream_out *out = (struct stream_out *)stream;
1725
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001726 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001727 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001728 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1729 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001730
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001731 return out->config.period_size *
1732 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733}
1734
1735static uint32_t out_get_channels(const struct audio_stream *stream)
1736{
1737 struct stream_out *out = (struct stream_out *)stream;
1738
1739 return out->channel_mask;
1740}
1741
1742static audio_format_t out_get_format(const struct audio_stream *stream)
1743{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001744 struct stream_out *out = (struct stream_out *)stream;
1745
1746 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747}
1748
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001749static int out_set_format(struct audio_stream *stream __unused,
1750 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751{
1752 return -ENOSYS;
1753}
1754
1755static int out_standby(struct audio_stream *stream)
1756{
1757 struct stream_out *out = (struct stream_out *)stream;
1758 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301760 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1761 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001762 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1763 /* Ignore standby in case of voip call because the voip output
1764 * stream is closed in adev_close_output_stream()
1765 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301766 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001767 return 0;
1768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001772 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001774 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 if (out->pcm) {
1776 pcm_close(out->pcm);
1777 out->pcm = NULL;
1778 }
1779 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001780 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001782 out->gapless_mdata.encoder_delay = 0;
1783 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 if (out->compr != NULL) {
1785 compress_close(out->compr);
1786 out->compr = NULL;
1787 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001790 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 }
1792 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001793 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 return 0;
1795}
1796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001797static int out_dump(const struct audio_stream *stream __unused,
1798 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 return 0;
1801}
1802
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001803static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1804{
1805 int ret = 0;
1806 char value[32];
Yadav Anamikafbcef792015-08-19 16:15:00 +05301807 bool is_meta_data_params = false;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001808
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001809 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001810 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 return -EINVAL;
1812 }
1813
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001814 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1815 if (ret >= 0) {
1816 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1817 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1818 ALOGV("ADTS format is set in offload mode");
1819 }
Yadav Anamikafbcef792015-08-19 16:15:00 +05301820 out->send_new_metadata = 1;
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001821 }
1822
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301823 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001824
Yadav Anamikafbcef792015-08-19 16:15:00 +05301825 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1826 if(ret >= 0)
1827 is_meta_data_params = true;
1828 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1829 if(ret >= 0)
1830 is_meta_data_params = true;
1831 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1832 if(ret >= 0)
1833 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001834 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1835 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301836 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301837 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001839 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1840 if (ret >= 0) {
Yadav Anamikafbcef792015-08-19 16:15:00 +05301841 is_meta_data_params = true;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301842 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843 }
1844
Yadav Anamikafbcef792015-08-19 16:15:00 +05301845 if(!is_meta_data_params) {
1846 ALOGV("%s: Not gapless meta data params", __func__);
1847 return 0;
1848 }
1849 out->send_new_metadata = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 ALOGV("%s new encoder delay %u and padding %u", __func__,
1851 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1852
1853 return 0;
1854}
1855
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001856static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1857{
1858 return out == adev->primary_output || out == adev->voice_tx_output;
1859}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1862{
1863 struct stream_out *out = (struct stream_out *)stream;
1864 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001865 struct audio_usecase *usecase;
1866 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 struct str_parms *parms;
1868 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001869 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001870 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871
sangwoobc677242013-08-08 16:53:43 +09001872 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001873 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301875 if (!parms)
1876 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001877 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1878 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001881 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301884 * When HDMI cable is unplugged/usb hs is disconnected the
1885 * music playback is paused and the policy manager sends routing=0
1886 * But the audioflingercontinues to write data until standby time
1887 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 * Avoid this by routing audio to speaker until standby.
1889 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301890 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1891 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001892 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001893 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1894 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001895 }
1896
1897 /*
1898 * select_devices() call below switches all the usecases on the same
1899 * backend to the new device. Refer to check_usecases_codec_backend() in
1900 * the select_devices(). But how do we undo this?
1901 *
1902 * For example, music playback is active on headset (deep-buffer usecase)
1903 * and if we go to ringtones and select a ringtone, low-latency usecase
1904 * will be started on headset+speaker. As we can't enable headset+speaker
1905 * and headset devices at the same time, select_devices() switches the music
1906 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1907 * So when the ringtone playback is completed, how do we undo the same?
1908 *
1909 * We are relying on the out_set_parameters() call on deep-buffer output,
1910 * once the ringtone playback is ended.
1911 * NOTE: We should not check if the current devices are same as new devices.
1912 * Because select_devices() must be called to switch back the music
1913 * playback to headset.
1914 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001915 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 out->devices = val;
1917
1918 if (!out->standby)
1919 select_devices(adev, out->usecase);
1920
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001921 if (output_drives_call(adev, out)) {
1922 if(!voice_is_in_call(adev)) {
1923 if (adev->mode == AUDIO_MODE_IN_CALL) {
1924 adev->current_call_output = out;
1925 ret = voice_start_call(adev);
1926 }
1927 } else {
1928 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001929 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001930 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001931 }
1932 }
1933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001935 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001937
1938 if (out == adev->primary_output) {
1939 pthread_mutex_lock(&adev->lock);
1940 audio_extn_set_parameters(adev, parms);
1941 pthread_mutex_unlock(&adev->lock);
1942 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001943 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001944 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001945 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001946
1947 audio_extn_dts_create_state_notifier_node(out->usecase);
1948 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1949 popcount(out->channel_mask),
1950 out->playback_started);
1951
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001952 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001953 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301956error:
Eric Laurent994a6932013-07-17 11:51:42 -07001957 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 return ret;
1959}
1960
1961static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1962{
1963 struct stream_out *out = (struct stream_out *)stream;
1964 struct str_parms *query = str_parms_create_str(keys);
1965 char *str;
1966 char value[256];
1967 struct str_parms *reply = str_parms_create();
1968 size_t i, j;
1969 int ret;
1970 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001971
1972 if (!query || !reply) {
1973 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1974 return NULL;
1975 }
1976
Eric Laurent994a6932013-07-17 11:51:42 -07001977 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1979 if (ret >= 0) {
1980 value[0] = '\0';
1981 i = 0;
1982 while (out->supported_channel_masks[i] != 0) {
1983 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1984 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1985 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001986 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001988 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 first = false;
1990 break;
1991 }
1992 }
1993 i++;
1994 }
1995 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1996 str = str_parms_to_str(reply);
1997 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001998 voice_extn_out_get_parameters(out, query, reply);
1999 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002000 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002001 free(str);
2002 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002003 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002005
2006 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2007 if (ret >= 0) {
2008 value[0] = '\0';
2009 i = 0;
2010 first = true;
2011 while (out->supported_formats[i] != 0) {
2012 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2013 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2014 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002015 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002016 }
2017 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2018 first = false;
2019 break;
2020 }
2021 }
2022 i++;
2023 }
2024 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2025 str = str_parms_to_str(reply);
2026 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 str_parms_destroy(query);
2028 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002029 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 return str;
2031}
2032
2033static uint32_t out_get_latency(const struct audio_stream_out *stream)
2034{
2035 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002036 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037
Alexy Josephaa54c872014-12-03 02:46:47 -08002038 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002039 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002040 } else {
2041 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002043 }
2044
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302045 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002046 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047}
2048
2049static int out_set_volume(struct audio_stream_out *stream, float left,
2050 float right)
2051{
Eric Laurenta9024de2013-04-04 09:19:12 -07002052 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002053 int volume[2];
2054
Eric Laurenta9024de2013-04-04 09:19:12 -07002055 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2056 /* only take left channel into account: the API is for stereo anyway */
2057 out->muted = (left == 0.0f);
2058 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002059 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002060 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2061 /*
2062 * Set mute or umute on HDMI passthrough stream.
2063 * Only take left channel into account.
2064 * Mute is 0 and unmute 1
2065 */
2066 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2067 } else {
2068 char mixer_ctl_name[128];
2069 struct audio_device *adev = out->dev;
2070 struct mixer_ctl *ctl;
2071 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002072 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002073
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002074 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2075 "Compress Playback %d Volume", pcm_device_id);
2076 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2077 if (!ctl) {
2078 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2079 __func__, mixer_ctl_name);
2080 return -EINVAL;
2081 }
2082 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2083 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2084 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2085 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002086 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002087 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 return -ENOSYS;
2090}
2091
2092static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2093 size_t bytes)
2094{
2095 struct stream_out *out = (struct stream_out *)stream;
2096 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302097 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002098 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302101
Naresh Tanniru80659832014-06-04 18:17:56 +05302102 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002103 // increase written size during SSR to avoid mismatch
2104 // with the written frames count in AF
2105 if (!is_offload_usecase(out->usecase))
2106 out->written += bytes / (out->config.channels * sizeof(short));
2107
Naresh Tanniru80659832014-06-04 18:17:56 +05302108 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302109 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302110 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302111 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002112 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302113 //during SSR for compress usecase we should return error to flinger
2114 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2115 pthread_mutex_unlock(&out->lock);
2116 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302117 }
2118 }
2119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002121 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002122 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002123 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2124 ret = voice_extn_compress_voip_start_output_stream(out);
2125 else
2126 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002127 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002130 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 goto exit;
2132 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302135 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2136 setChannelStatus(out, buffer, bytes);
2137 adev->mChannelStatusSet = true;
2138 }
2139
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002140 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002141 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002142 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002143 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002144 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2145 out->send_new_metadata = 0;
2146 }
2147
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302149 if (ret < 0)
2150 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002151 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002152 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302153 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302155 } else if (-ENETRESET == ret) {
2156 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2157 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2158 pthread_mutex_unlock(&out->lock);
2159 out_standby(&out->stream.common);
2160 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302162 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002163 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002164 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 out->playback_started = 1;
2166 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002167
2168 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2169 popcount(out->channel_mask),
2170 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 }
2172 pthread_mutex_unlock(&out->lock);
2173 return ret;
2174 } else {
2175 if (out->pcm) {
2176 if (out->muted)
2177 memset((void *)buffer, 0, bytes);
2178 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002179 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2180 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2181 else
2182 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302183 if (ret < 0)
2184 ret = -errno;
2185 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002186 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 }
2189
2190exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302191 /* ToDo: There may be a corner case when SSR happens back to back during
2192 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302193 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302194 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302195 }
2196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 pthread_mutex_unlock(&out->lock);
2198
2199 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002200 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002201 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302202 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302203 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302204 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302205 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302206 out->standby = true;
2207 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002209 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302210 out_get_sample_rate(&out->stream.common));
2211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 }
2213 return bytes;
2214}
2215
2216static int out_get_render_position(const struct audio_stream_out *stream,
2217 uint32_t *dsp_frames)
2218{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302220 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002221
2222 if (dsp_frames == NULL)
2223 return -EINVAL;
2224
2225 *dsp_frames = 0;
2226 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002227 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 pthread_mutex_lock(&out->lock);
2229 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302230 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302232 if (ret < 0)
2233 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 ALOGVV("%s rendered frames %d sample_rate %d",
2235 __func__, *dsp_frames, out->sample_rate);
2236 }
2237 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302238 if (-ENETRESET == ret) {
2239 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2240 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2241 return -EINVAL;
2242 } else if(ret < 0) {
2243 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2244 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302245 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2246 /*
2247 * Handle corner case where compress session is closed during SSR
2248 * and timestamp is queried
2249 */
2250 ALOGE(" ERROR: sound card not active, return error");
2251 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302252 } else {
2253 return 0;
2254 }
Zhou Song32a556e2015-05-05 10:46:56 +08002255 } else if (audio_is_linear_pcm(out->format)) {
2256 *dsp_frames = out->written;
2257 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 } else
2259 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260}
2261
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002262static int out_add_audio_effect(const struct audio_stream *stream __unused,
2263 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264{
2265 return 0;
2266}
2267
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002268static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2269 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270{
2271 return 0;
2272}
2273
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002274static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2275 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276{
2277 return -EINVAL;
2278}
2279
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002280static int out_get_presentation_position(const struct audio_stream_out *stream,
2281 uint64_t *frames, struct timespec *timestamp)
2282{
2283 struct stream_out *out = (struct stream_out *)stream;
2284 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002285 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002286
2287 pthread_mutex_lock(&out->lock);
2288
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002289 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002290 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302291 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002292 &out->sample_rate);
2293 ALOGVV("%s rendered frames %ld sample_rate %d",
2294 __func__, dsp_frames, out->sample_rate);
2295 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302296 if (ret < 0)
2297 ret = -errno;
2298 if (-ENETRESET == ret) {
2299 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2300 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2301 ret = -EINVAL;
2302 } else
2303 ret = 0;
2304
Eric Laurent949a0892013-09-20 09:20:13 -07002305 /* this is the best we can do */
2306 clock_gettime(CLOCK_MONOTONIC, timestamp);
2307 }
2308 } else {
2309 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002310 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002311 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2312 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002313 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002314 // This adjustment accounts for buffering after app processor.
2315 // It is based on estimated DSP latency per use case, rather than exact.
2316 signed_frames -=
2317 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2318
Eric Laurent949a0892013-09-20 09:20:13 -07002319 // It would be unusual for this value to be negative, but check just in case ...
2320 if (signed_frames >= 0) {
2321 *frames = signed_frames;
2322 ret = 0;
2323 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002324 }
2325 }
2326 }
2327
2328 pthread_mutex_unlock(&out->lock);
2329
2330 return ret;
2331}
2332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333static int out_set_callback(struct audio_stream_out *stream,
2334 stream_callback_t callback, void *cookie)
2335{
2336 struct stream_out *out = (struct stream_out *)stream;
2337
2338 ALOGV("%s", __func__);
2339 pthread_mutex_lock(&out->lock);
2340 out->offload_callback = callback;
2341 out->offload_cookie = cookie;
2342 pthread_mutex_unlock(&out->lock);
2343 return 0;
2344}
2345
2346static int out_pause(struct audio_stream_out* stream)
2347{
2348 struct stream_out *out = (struct stream_out *)stream;
2349 int status = -ENOSYS;
2350 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002351 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002352 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 pthread_mutex_lock(&out->lock);
2354 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302355 struct audio_device *adev = out->dev;
2356 int snd_scard_state = get_snd_card_state(adev);
2357
2358 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2359 status = compress_pause(out->compr);
2360
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002362
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302363 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002364 audio_extn_dts_notify_playback_state(out->usecase, 0,
2365 out->sample_rate, popcount(out->channel_mask),
2366 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 }
2368 pthread_mutex_unlock(&out->lock);
2369 }
2370 return status;
2371}
2372
2373static int out_resume(struct audio_stream_out* stream)
2374{
2375 struct stream_out *out = (struct stream_out *)stream;
2376 int status = -ENOSYS;
2377 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002378 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002379 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 status = 0;
2381 pthread_mutex_lock(&out->lock);
2382 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302383 struct audio_device *adev = out->dev;
2384 int snd_scard_state = get_snd_card_state(adev);
2385
2386 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2387 status = compress_resume(out->compr);
2388
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002390
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302391 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002392 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2393 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 }
2395 pthread_mutex_unlock(&out->lock);
2396 }
2397 return status;
2398}
2399
2400static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2401{
2402 struct stream_out *out = (struct stream_out *)stream;
2403 int status = -ENOSYS;
2404 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002405 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 pthread_mutex_lock(&out->lock);
2407 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2408 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2409 else
2410 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2411 pthread_mutex_unlock(&out->lock);
2412 }
2413 return status;
2414}
2415
2416static int out_flush(struct audio_stream_out* stream)
2417{
2418 struct stream_out *out = (struct stream_out *)stream;
2419 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002420 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002421 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422 pthread_mutex_lock(&out->lock);
2423 stop_compressed_output_l(out);
2424 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002425 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002426 return 0;
2427 }
2428 return -ENOSYS;
2429}
2430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431/** audio_stream_in implementation **/
2432static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2433{
2434 struct stream_in *in = (struct stream_in *)stream;
2435
2436 return in->config.rate;
2437}
2438
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002439static int in_set_sample_rate(struct audio_stream *stream __unused,
2440 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441{
2442 return -ENOSYS;
2443}
2444
2445static size_t in_get_buffer_size(const struct audio_stream *stream)
2446{
2447 struct stream_in *in = (struct stream_in *)stream;
2448
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002449 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2450 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002451 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2452 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002453
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002454 return in->config.period_size *
2455 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456}
2457
2458static uint32_t in_get_channels(const struct audio_stream *stream)
2459{
2460 struct stream_in *in = (struct stream_in *)stream;
2461
2462 return in->channel_mask;
2463}
2464
2465static audio_format_t in_get_format(const struct audio_stream *stream)
2466{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002467 struct stream_in *in = (struct stream_in *)stream;
2468
2469 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470}
2471
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002472static int in_set_format(struct audio_stream *stream __unused,
2473 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474{
2475 return -ENOSYS;
2476}
2477
2478static int in_standby(struct audio_stream *stream)
2479{
2480 struct stream_in *in = (struct stream_in *)stream;
2481 struct audio_device *adev = in->dev;
2482 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302483 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2484 stream, in->usecase, use_case_table[in->usecase]);
2485
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002486 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2487 /* Ignore standby in case of voip call because the voip input
2488 * stream is closed in adev_close_input_stream()
2489 */
2490 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2491 return status;
2492 }
2493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002495 if (!in->standby && in->is_st_session) {
2496 ALOGD("%s: sound trigger pcm stop lab", __func__);
2497 audio_extn_sound_trigger_stop_lab(in);
2498 in->standby = 1;
2499 }
2500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002502 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002504 if (in->pcm) {
2505 pcm_close(in->pcm);
2506 in->pcm = NULL;
2507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002509 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 }
2511 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002512 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 return status;
2514}
2515
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002516static int in_dump(const struct audio_stream *stream __unused,
2517 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518{
2519 return 0;
2520}
2521
2522static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2523{
2524 struct stream_in *in = (struct stream_in *)stream;
2525 struct audio_device *adev = in->dev;
2526 struct str_parms *parms;
2527 char *str;
2528 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002529 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302531 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 parms = str_parms_create_str(kvpairs);
2533
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302534 if (!parms)
2535 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002537 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002538
2539 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2540 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 val = atoi(value);
2542 /* no audio source uses val == 0 */
2543 if ((in->source != val) && (val != 0)) {
2544 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002545 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2546 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2547 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2548 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002549 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002550 err = voice_extn_compress_voip_open_input_stream(in);
2551 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002552 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002553 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002554 }
2555 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 }
2557 }
2558
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002559 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2560 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002562 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 in->device = val;
2564 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002565 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002566 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 }
2568 }
2569
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002570done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002572 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573
2574 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302575error:
Eric Laurent994a6932013-07-17 11:51:42 -07002576 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 return ret;
2578}
2579
2580static char* in_get_parameters(const struct audio_stream *stream,
2581 const char *keys)
2582{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002583 struct stream_in *in = (struct stream_in *)stream;
2584 struct str_parms *query = str_parms_create_str(keys);
2585 char *str;
2586 char value[256];
2587 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002588
2589 if (!query || !reply) {
2590 ALOGE("in_get_parameters: failed to create query or reply");
2591 return NULL;
2592 }
2593
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002594 ALOGV("%s: enter: keys - %s", __func__, keys);
2595
2596 voice_extn_in_get_parameters(in, query, reply);
2597
2598 str = str_parms_to_str(reply);
2599 str_parms_destroy(query);
2600 str_parms_destroy(reply);
2601
2602 ALOGV("%s: exit: returns - %s", __func__, str);
2603 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604}
2605
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002606static int in_set_gain(struct audio_stream_in *stream __unused,
2607 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608{
2609 return 0;
2610}
2611
2612static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2613 size_t bytes)
2614{
2615 struct stream_in *in = (struct stream_in *)stream;
2616 struct audio_device *adev = in->dev;
2617 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302618 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302621
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002622 if (in->is_st_session) {
2623 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2624 /* Read from sound trigger HAL */
2625 audio_extn_sound_trigger_read(in, buffer, bytes);
2626 pthread_mutex_unlock(&in->lock);
2627 return bytes;
2628 }
2629
2630 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2631 ALOGD(" %s: sound card is not active/SSR state", __func__);
2632 ret= -EIO;;
2633 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302634 }
2635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002637 pthread_mutex_lock(&adev->lock);
2638 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2639 ret = voice_extn_compress_voip_start_input_stream(in);
2640 else
2641 ret = start_input_stream(in);
2642 pthread_mutex_unlock(&adev->lock);
2643 if (ret != 0) {
2644 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 }
2646 in->standby = 0;
2647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648
2649 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002650 if (audio_extn_ssr_get_enabled() &&
2651 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002652 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002653 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2654 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002655 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2656 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002657 else
2658 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302659 if (ret < 0)
2660 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 }
2662
2663 /*
2664 * Instead of writing zeroes here, we could trust the hardware
2665 * to always provide zeroes when muted.
2666 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302667 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2668 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 memset(buffer, 0, bytes);
2670
2671exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302672 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302673 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002674 if (-ENETRESET == ret)
2675 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 pthread_mutex_unlock(&in->lock);
2678
2679 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302680 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302681 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302682 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302683 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302684 in->standby = true;
2685 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302686 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002688 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002689 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302690 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 }
2692 return bytes;
2693}
2694
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002695static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696{
2697 return 0;
2698}
2699
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002700static int add_remove_audio_effect(const struct audio_stream *stream,
2701 effect_handle_t effect,
2702 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002704 struct stream_in *in = (struct stream_in *)stream;
2705 int status = 0;
2706 effect_descriptor_t desc;
2707
2708 status = (*effect)->get_descriptor(effect, &desc);
2709 if (status != 0)
2710 return status;
2711
2712 pthread_mutex_lock(&in->lock);
2713 pthread_mutex_lock(&in->dev->lock);
2714 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2715 in->enable_aec != enable &&
2716 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2717 in->enable_aec = enable;
2718 if (!in->standby)
2719 select_devices(in->dev, in->usecase);
2720 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002721 if (in->enable_ns != enable &&
2722 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2723 in->enable_ns = enable;
2724 if (!in->standby)
2725 select_devices(in->dev, in->usecase);
2726 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002727 pthread_mutex_unlock(&in->dev->lock);
2728 pthread_mutex_unlock(&in->lock);
2729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 return 0;
2731}
2732
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002733static int in_add_audio_effect(const struct audio_stream *stream,
2734 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735{
Eric Laurent994a6932013-07-17 11:51:42 -07002736 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002737 return add_remove_audio_effect(stream, effect, true);
2738}
2739
2740static int in_remove_audio_effect(const struct audio_stream *stream,
2741 effect_handle_t effect)
2742{
Eric Laurent994a6932013-07-17 11:51:42 -07002743 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002744 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745}
2746
2747static int adev_open_output_stream(struct audio_hw_device *dev,
2748 audio_io_handle_t handle,
2749 audio_devices_t devices,
2750 audio_output_flags_t flags,
2751 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002752 struct audio_stream_out **stream_out,
2753 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754{
2755 struct audio_device *adev = (struct audio_device *)dev;
2756 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002757 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002758 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302761
2762 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2763 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2764 ALOGE(" sound card is not active rejecting compress output open request");
2765 return -EINVAL;
2766 }
2767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2769
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302770 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2771 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2772 devices, flags, &out->stream);
2773
2774
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002775 if (!out) {
2776 return -ENOMEM;
2777 }
2778
Haynes Mathew George204045b2015-02-25 20:32:03 -08002779 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2780 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 if (devices == AUDIO_DEVICE_NONE)
2783 devices = AUDIO_DEVICE_OUT_SPEAKER;
2784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 out->flags = flags;
2786 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002787 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002788 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789 out->sample_rate = config->sample_rate;
2790 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2791 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002792 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002793 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002794 out->non_blocking = 0;
2795 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302797 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2798 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002799 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2800 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2801
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002802 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002803 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2804 ret = read_hdmi_channel_masks(out);
2805
2806 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2807 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002808 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002809 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002810 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002811
2812 if (config->sample_rate == 0)
2813 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2814 if (config->channel_mask == 0)
2815 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2816
2817 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2820 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002822 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002824 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2825 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002826 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002827 ret = voice_extn_compress_voip_open_output_stream(out);
2828 if (ret != 0) {
2829 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2830 __func__, ret);
2831 goto error_open;
2832 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2834 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2835 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2836 ALOGE("%s: Unsupported Offload information", __func__);
2837 ret = -EINVAL;
2838 goto error_open;
2839 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002840
2841 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2842 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2843 ALOGV("read and update_pass through formats");
2844 ret = audio_extn_dolby_update_passt_formats(adev, out);
2845 if(ret != 0) {
2846 goto error_open;
2847 }
2848 if(config->offload_info.format == 0)
2849 config->offload_info.format = out->supported_formats[0];
2850 }
2851
Mingming Yin90310102013-11-13 16:57:00 -08002852 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002853 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854 ALOGE("%s: Unsupported audio format", __func__);
2855 ret = -EINVAL;
2856 goto error_open;
2857 }
2858
2859 out->compr_config.codec = (struct snd_codec *)
2860 calloc(1, sizeof(struct snd_codec));
2861
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002862 if (!out->compr_config.codec) {
2863 ret = -ENOMEM;
2864 goto error_open;
2865 }
2866
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002867 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 if (config->offload_info.channel_mask)
2869 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002870 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002872 config->offload_info.channel_mask = config->channel_mask;
2873 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002874 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 out->sample_rate = config->offload_info.sample_rate;
2876
2877 out->stream.set_callback = out_set_callback;
2878 out->stream.pause = out_pause;
2879 out->stream.resume = out_resume;
2880 out->stream.drain = out_drain;
2881 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002882 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002884 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002885 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002886 audio_extn_dolby_get_snd_codec_id(adev, out,
2887 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002888 else
2889 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302891 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002892 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002893 platform_get_pcm_offload_buffer_size(&config->offload_info);
2894 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2895 out->compr_config.fragment_size =
2896 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002897 } else {
2898 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002899 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002900 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2902 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002903 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 out->compr_config.codec->bit_rate =
2905 config->offload_info.bit_rate;
2906 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002907 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302909 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002910 /*TODO: Do we need to change it for passthrough */
2911 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002912
Mingming Yin3ee55c62014-08-04 14:23:35 -07002913 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2914 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002915 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2916 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002918 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2919
Mingming Yin3ee55c62014-08-04 14:23:35 -07002920 if (out->bit_width == 24) {
2921 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2922 }
2923
Amit Shekhar6f461b12014-08-01 14:52:58 -07002924 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302925 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2928 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002929
Sharad Sangleb27354b2015-06-18 15:58:55 +05302930 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002931 //this flag is set from framework only if its for PCM formats
2932 //no need to check for PCM format again
2933 out->non_blocking = 0;
2934 out->use_small_bufs = true;
2935 ALOGI("Keep write blocking for small buff: non_blockling %d",
2936 out->non_blocking);
2937 }
2938
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002939 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002940 out->offload_state = OFFLOAD_STATE_IDLE;
2941 out->playback_started = 0;
2942
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002943 audio_extn_dts_create_state_notifier_node(out->usecase);
2944
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 create_offload_callback_thread(out);
2946 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2947 __func__, config->offload_info.version,
2948 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002949 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002950 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002951 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2952 ret = voice_check_and_set_incall_music_usecase(adev, out);
2953 if (ret != 0) {
2954 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2955 __func__, ret);
2956 goto error_open;
2957 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002958 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2959 if (config->sample_rate == 0)
2960 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2961 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2962 config->sample_rate != 8000) {
2963 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2964 ret = -EINVAL;
2965 goto error_open;
2966 }
2967 out->sample_rate = config->sample_rate;
2968 out->config.rate = config->sample_rate;
2969 if (config->format == AUDIO_FORMAT_DEFAULT)
2970 config->format = AUDIO_FORMAT_PCM_16_BIT;
2971 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2972 config->format = AUDIO_FORMAT_PCM_16_BIT;
2973 ret = -EINVAL;
2974 goto error_open;
2975 }
2976 out->format = config->format;
2977 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2978 out->config = pcm_config_afe_proxy_playback;
2979 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002980 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002981 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2983 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002984 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002985 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2986 format = AUDIO_FORMAT_PCM_16_BIT;
2987 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2988 out->config = pcm_config_deep_buffer;
2989 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002990 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002991 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002992 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002993 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002994 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002995 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 }
2997
Amit Shekhar1d896042014-10-03 13:16:09 -07002998 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2999 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003000 /* TODO remove this hardcoding and check why width is zero*/
3001 if (out->bit_width == 0)
3002 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003003 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3004 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003005 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303006 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003007 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3008 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3009 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003010 if(adev->primary_output == NULL)
3011 adev->primary_output = out;
3012 else {
3013 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003014 ret = -EEXIST;
3015 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003016 }
3017 }
3018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 /* Check if this usecase is already existing */
3020 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003021 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3022 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003025 ret = -EEXIST;
3026 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 }
3028 pthread_mutex_unlock(&adev->lock);
3029
3030 out->stream.common.get_sample_rate = out_get_sample_rate;
3031 out->stream.common.set_sample_rate = out_set_sample_rate;
3032 out->stream.common.get_buffer_size = out_get_buffer_size;
3033 out->stream.common.get_channels = out_get_channels;
3034 out->stream.common.get_format = out_get_format;
3035 out->stream.common.set_format = out_set_format;
3036 out->stream.common.standby = out_standby;
3037 out->stream.common.dump = out_dump;
3038 out->stream.common.set_parameters = out_set_parameters;
3039 out->stream.common.get_parameters = out_get_parameters;
3040 out->stream.common.add_audio_effect = out_add_audio_effect;
3041 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3042 out->stream.get_latency = out_get_latency;
3043 out->stream.set_volume = out_set_volume;
3044 out->stream.write = out_write;
3045 out->stream.get_render_position = out_get_render_position;
3046 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003047 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003050 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003051 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052
3053 config->format = out->stream.common.get_format(&out->stream.common);
3054 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3055 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3056
3057 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303058 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3059 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003060
3061 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3062 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3063 popcount(out->channel_mask), out->playback_started);
3064
Eric Laurent994a6932013-07-17 11:51:42 -07003065 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003067
3068error_open:
3069 free(out);
3070 *stream_out = NULL;
3071 ALOGD("%s: exit: ret %d", __func__, ret);
3072 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073}
3074
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003075static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076 struct audio_stream_out *stream)
3077{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003078 struct stream_out *out = (struct stream_out *)stream;
3079 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003080 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303082 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3083
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003084 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303085 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003086 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303087 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003088 if(ret != 0)
3089 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3090 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003091 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003092 out_standby(&stream->common);
3093
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003094 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003095 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003097 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 if (out->compr_config.codec != NULL)
3099 free(out->compr_config.codec);
3100 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003101
3102 if (adev->voice_tx_output == out)
3103 adev->voice_tx_output = NULL;
3104
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 pthread_cond_destroy(&out->cond);
3106 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003108 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109}
3110
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003111static void close_compress_sessions(struct audio_device *adev)
3112{
Mingming Yin7b762e72015-03-04 13:47:32 -08003113 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303114 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003115 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003116 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303117
3118 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003119 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303120 if (is_offload_usecase(usecase->id)) {
3121 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003122 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3123 out = usecase->stream.out;
3124 pthread_mutex_unlock(&adev->lock);
3125 out_standby(&out->stream.common);
3126 pthread_mutex_lock(&adev->lock);
3127 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303128 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003129 }
3130 pthread_mutex_unlock(&adev->lock);
3131}
3132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3134{
3135 struct audio_device *adev = (struct audio_device *)dev;
3136 struct str_parms *parms;
3137 char *str;
3138 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003139 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003140 int ret;
3141 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003143 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303146 if (!parms)
3147 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003148 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3149 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303150 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303151 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303152 struct listnode *node;
3153 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303154 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303155 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003156 //close compress sessions on OFFLINE status
3157 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158 } else if (strstr(snd_card_status, "ONLINE")) {
3159 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303160 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303161 if (!platform_is_acdb_initialized(adev->platform)) {
3162 ret = platform_acdb_init(adev->platform);
3163 if(ret)
3164 ALOGE("acdb initialization is failed");
3165
3166 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303167 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303168 }
3169
3170 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003171 status = voice_set_parameters(adev, parms);
3172 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003173 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003175 status = platform_set_parameters(adev->platform, parms);
3176 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003177 goto done;
3178
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003179 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3180 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003181 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3183 adev->bluetooth_nrec = true;
3184 else
3185 adev->bluetooth_nrec = false;
3186 }
3187
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003188 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3189 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3191 adev->screen_off = false;
3192 else
3193 adev->screen_off = true;
3194 }
3195
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003196 ret = str_parms_get_int(parms, "rotation", &val);
3197 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003198 bool reverse_speakers = false;
3199 switch(val) {
3200 // FIXME: note that the code below assumes that the speakers are in the correct placement
3201 // relative to the user when the device is rotated 90deg from its default rotation. This
3202 // assumption is device-specific, not platform-specific like this code.
3203 case 270:
3204 reverse_speakers = true;
3205 break;
3206 case 0:
3207 case 90:
3208 case 180:
3209 break;
3210 default:
3211 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003212 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003213 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003214 if (status == 0) {
3215 if (adev->speaker_lr_swap != reverse_speakers) {
3216 adev->speaker_lr_swap = reverse_speakers;
3217 // only update the selected device if there is active pcm playback
3218 struct audio_usecase *usecase;
3219 struct listnode *node;
3220 list_for_each(node, &adev->usecase_list) {
3221 usecase = node_to_item(node, struct audio_usecase, list);
3222 if (usecase->type == PCM_PLAYBACK) {
3223 select_devices(adev, usecase->id);
3224 break;
3225 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003226 }
3227 }
3228 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003229 }
3230
Mingming Yin514a8bc2014-07-29 15:22:21 -07003231 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3232 if (ret >= 0) {
3233 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3234 adev->bt_wb_speech_enabled = true;
3235 else
3236 adev->bt_wb_speech_enabled = false;
3237 }
3238
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003239 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3240 if (ret >= 0) {
3241 val = atoi(value);
3242 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3243 ALOGV("cache new edid");
3244 platform_cache_edid(adev->platform);
3245 }
3246 }
3247
3248 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3249 if (ret >= 0) {
3250 val = atoi(value);
3251 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3252 ALOGV("invalidate cached edid");
3253 platform_invalidate_edid(adev->platform);
3254 }
3255 }
3256
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003257 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003258
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003259done:
3260 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003261 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303262error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003263 ALOGV("%s: exit with code(%d)", __func__, status);
3264 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265}
3266
3267static char* adev_get_parameters(const struct audio_hw_device *dev,
3268 const char *keys)
3269{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003270 struct audio_device *adev = (struct audio_device *)dev;
3271 struct str_parms *reply = str_parms_create();
3272 struct str_parms *query = str_parms_create_str(keys);
3273 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303274 char value[256] = {0};
3275 int ret = 0;
3276
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003277 if (!query || !reply) {
3278 ALOGE("adev_get_parameters: failed to create query or reply");
3279 return NULL;
3280 }
3281
Naresh Tannirud7205b62014-06-20 02:54:48 +05303282 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3283 sizeof(value));
3284 if (ret >=0) {
3285 int val = 1;
3286 pthread_mutex_lock(&adev->snd_card_status.lock);
3287 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3288 val = 0;
3289 pthread_mutex_unlock(&adev->snd_card_status.lock);
3290 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3291 goto exit;
3292 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003293
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003294 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003295 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003296 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003297 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303298 pthread_mutex_unlock(&adev->lock);
3299
Naresh Tannirud7205b62014-06-20 02:54:48 +05303300exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003301 str = str_parms_to_str(reply);
3302 str_parms_destroy(query);
3303 str_parms_destroy(reply);
3304
3305 ALOGV("%s: exit: returns - %s", __func__, str);
3306 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307}
3308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003309static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310{
3311 return 0;
3312}
3313
3314static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3315{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003316 int ret;
3317 struct audio_device *adev = (struct audio_device *)dev;
3318 pthread_mutex_lock(&adev->lock);
3319 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003320 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003321 pthread_mutex_unlock(&adev->lock);
3322 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323}
3324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003325static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3326 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327{
3328 return -ENOSYS;
3329}
3330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003331static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3332 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333{
3334 return -ENOSYS;
3335}
3336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003337static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3338 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339{
3340 return -ENOSYS;
3341}
3342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003343static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3344 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345{
3346 return -ENOSYS;
3347}
3348
3349static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3350{
3351 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 pthread_mutex_lock(&adev->lock);
3354 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003355 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003357 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3358 voice_is_in_call(adev)) {
3359 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303360 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003361 adev->current_call_output = NULL;
3362 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 }
3364 pthread_mutex_unlock(&adev->lock);
3365 return 0;
3366}
3367
3368static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3369{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003370 int ret;
3371
3372 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003373 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003374 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3375 pthread_mutex_unlock(&adev->lock);
3376
3377 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378}
3379
3380static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3381{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003382 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 return 0;
3384}
3385
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003386static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 const struct audio_config *config)
3388{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003389 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003391 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3392 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393}
3394
3395static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003396 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 audio_devices_t devices,
3398 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003399 struct audio_stream_in **stream_in,
3400 audio_input_flags_t flags __unused,
3401 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003402 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403{
3404 struct audio_device *adev = (struct audio_device *)dev;
3405 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003406 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003407 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003408 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 *stream_in = NULL;
3411 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3412 return -EINVAL;
3413
3414 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003415
3416 if (!in) {
3417 ALOGE("failed to allocate input stream");
3418 return -ENOMEM;
3419 }
3420
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303421 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003422 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3423 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003425 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 in->stream.common.get_sample_rate = in_get_sample_rate;
3428 in->stream.common.set_sample_rate = in_set_sample_rate;
3429 in->stream.common.get_buffer_size = in_get_buffer_size;
3430 in->stream.common.get_channels = in_get_channels;
3431 in->stream.common.get_format = in_get_format;
3432 in->stream.common.set_format = in_set_format;
3433 in->stream.common.standby = in_standby;
3434 in->stream.common.dump = in_dump;
3435 in->stream.common.set_parameters = in_set_parameters;
3436 in->stream.common.get_parameters = in_get_parameters;
3437 in->stream.common.add_audio_effect = in_add_audio_effect;
3438 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3439 in->stream.set_gain = in_set_gain;
3440 in->stream.read = in_read;
3441 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3442
3443 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003444 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 in->standby = 1;
3447 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003448 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449
3450 /* Update config params with the requested sample rate and channels */
3451 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003452 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3453 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3454 is_low_latency = true;
3455#if LOW_LATENCY_CAPTURE_USE_CASE
3456 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3457#endif
3458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003461 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003463 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303464 if (adev->mode != AUDIO_MODE_IN_CALL) {
3465 ret = -EINVAL;
3466 goto err_open;
3467 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003468 if (config->sample_rate == 0)
3469 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3470 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3471 config->sample_rate != 8000) {
3472 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3473 ret = -EINVAL;
3474 goto err_open;
3475 }
3476 if (config->format == AUDIO_FORMAT_DEFAULT)
3477 config->format = AUDIO_FORMAT_PCM_16_BIT;
3478 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3479 config->format = AUDIO_FORMAT_PCM_16_BIT;
3480 ret = -EINVAL;
3481 goto err_open;
3482 }
3483
3484 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3485 in->config = pcm_config_afe_proxy_record;
3486 in->config.channels = channel_count;
3487 in->config.rate = config->sample_rate;
3488 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003489 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003490 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003491 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3492 ret = -EINVAL;
3493 goto err_open;
3494 }
3495 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003496 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003497 }
Mingming Yine62d7842013-10-25 16:26:03 -07003498 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003499 audio_extn_compr_cap_format_supported(config->format) &&
3500 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003501 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003502 } else {
3503 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003504 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003505 buffer_size = get_input_buffer_size(config->sample_rate,
3506 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003507 channel_count,
3508 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003509 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003510 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3511 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3512 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3513 (in->config.rate == 8000 || in->config.rate == 16000) &&
3514 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3515 voice_extn_compress_voip_open_input_stream(in);
3516 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003519 /* This stream could be for sound trigger lab,
3520 get sound trigger pcm if present */
3521 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303522 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003525 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003526 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527
3528err_open:
3529 free(in);
3530 *stream_in = NULL;
3531 return ret;
3532}
3533
3534static void adev_close_input_stream(struct audio_hw_device *dev,
3535 struct audio_stream_in *stream)
3536{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003537 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003538 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003539 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303540
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303541 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003542
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303543 /* Disable echo reference while closing input stream */
3544 platform_set_echo_reference(adev->platform, false);
3545
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003546 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303547 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003548 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303549 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003550 if (ret != 0)
3551 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3552 __func__, ret);
3553 } else
3554 in_standby(&stream->common);
3555
Mingming Yin7b762e72015-03-04 13:47:32 -08003556 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003557 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003558 audio_extn_ssr_deinit();
3559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560
Mingming Yine62d7842013-10-25 16:26:03 -07003561 if(audio_extn_compr_cap_enabled() &&
3562 audio_extn_compr_cap_format_supported(in->config.format))
3563 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003564
3565 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 return;
3567}
3568
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003569static int adev_dump(const audio_hw_device_t *device __unused,
3570 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571{
3572 return 0;
3573}
3574
3575static int adev_close(hw_device_t *device)
3576{
3577 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003578
3579 if (!adev)
3580 return 0;
3581
3582 pthread_mutex_lock(&adev_init_lock);
3583
3584 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003585 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003586 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003587 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003588 audio_route_free(adev->audio_route);
3589 free(adev->snd_dev_ref_cnt);
3590 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003591 free(device);
3592 adev = NULL;
3593 }
3594 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 return 0;
3596}
3597
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003598/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3599 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3600 * just that it _might_ work.
3601 */
3602static int period_size_is_plausible_for_low_latency(int period_size)
3603{
3604 switch (period_size) {
3605 case 160:
3606 case 240:
3607 case 320:
3608 case 480:
3609 return 1;
3610 default:
3611 return 0;
3612 }
3613}
3614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615static int adev_open(const hw_module_t *module, const char *name,
3616 hw_device_t **device)
3617{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003618 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003620 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3622
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003623 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003624 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003625 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003626 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003627 ALOGD("%s: returning existing instance of adev", __func__);
3628 ALOGD("%s: exit", __func__);
3629 pthread_mutex_unlock(&adev_init_lock);
3630 return 0;
3631 }
3632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 adev = calloc(1, sizeof(struct audio_device));
3634
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003635 if (!adev) {
3636 pthread_mutex_unlock(&adev_init_lock);
3637 return -ENOMEM;
3638 }
3639
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003640 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3643 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3644 adev->device.common.module = (struct hw_module_t *)module;
3645 adev->device.common.close = adev_close;
3646
3647 adev->device.init_check = adev_init_check;
3648 adev->device.set_voice_volume = adev_set_voice_volume;
3649 adev->device.set_master_volume = adev_set_master_volume;
3650 adev->device.get_master_volume = adev_get_master_volume;
3651 adev->device.set_master_mute = adev_set_master_mute;
3652 adev->device.get_master_mute = adev_get_master_mute;
3653 adev->device.set_mode = adev_set_mode;
3654 adev->device.set_mic_mute = adev_set_mic_mute;
3655 adev->device.get_mic_mute = adev_get_mic_mute;
3656 adev->device.set_parameters = adev_set_parameters;
3657 adev->device.get_parameters = adev_get_parameters;
3658 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3659 adev->device.open_output_stream = adev_open_output_stream;
3660 adev->device.close_output_stream = adev_close_output_stream;
3661 adev->device.open_input_stream = adev_open_input_stream;
3662 adev->device.close_input_stream = adev_close_input_stream;
3663 adev->device.dump = adev_dump;
3664
3665 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003667 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003668 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003671 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003672 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003673 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003674 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003675 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003676 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003677 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303678 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303679
3680 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3681 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003683 adev->platform = platform_init(adev);
3684 if (!adev->platform) {
3685 free(adev->snd_dev_ref_cnt);
3686 free(adev);
3687 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3688 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003689 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003690 return -EINVAL;
3691 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003692
Naresh Tanniru4c630392014-05-12 01:05:52 +05303693 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3694
Eric Laurentc4aef752013-09-12 17:45:53 -07003695 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3696 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3697 if (adev->visualizer_lib == NULL) {
3698 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3699 } else {
3700 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3701 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003702 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003703 "visualizer_hal_start_output");
3704 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003705 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003706 "visualizer_hal_stop_output");
3707 }
3708 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003709 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003710 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003711
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003712 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3713 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3714 if (adev->offload_effects_lib == NULL) {
3715 ALOGE("%s: DLOPEN failed for %s", __func__,
3716 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3717 } else {
3718 ALOGV("%s: DLOPEN successful for %s", __func__,
3719 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3720 adev->offload_effects_start_output =
3721 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3722 "offload_effects_bundle_hal_start_output");
3723 adev->offload_effects_stop_output =
3724 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3725 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003726 adev->offload_effects_set_hpx_state =
3727 (int (*)(bool))dlsym(adev->offload_effects_lib,
3728 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003729 }
3730 }
3731
Mingming Yin514a8bc2014-07-29 15:22:21 -07003732 adev->bt_wb_speech_enabled = false;
3733
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003734 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 *device = &adev->device.common;
3736
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003737 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3738 &adev->streams_output_cfg_list);
3739
Kiran Kandi910e1862013-10-29 13:29:42 -07003740 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003741
3742 char value[PROPERTY_VALUE_MAX];
3743 int trial;
3744 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3745 trial = atoi(value);
3746 if (period_size_is_plausible_for_low_latency(trial)) {
3747 pcm_config_low_latency.period_size = trial;
3748 pcm_config_low_latency.start_threshold = trial / 4;
3749 pcm_config_low_latency.avail_min = trial / 4;
3750 configured_low_latency_capture_period_size = trial;
3751 }
3752 }
3753 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3754 trial = atoi(value);
3755 if (period_size_is_plausible_for_low_latency(trial)) {
3756 configured_low_latency_capture_period_size = trial;
3757 }
3758 }
3759
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003760 pthread_mutex_unlock(&adev_init_lock);
3761
Eric Laurent994a6932013-07-17 11:51:42 -07003762 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 return 0;
3764}
3765
3766static struct hw_module_methods_t hal_module_methods = {
3767 .open = adev_open,
3768};
3769
3770struct audio_module HAL_MODULE_INFO_SYM = {
3771 .common = {
3772 .tag = HARDWARE_MODULE_TAG,
3773 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3774 .hal_api_version = HARDWARE_HAL_API_VERSION,
3775 .id = AUDIO_HARDWARE_MODULE_ID,
3776 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003777 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 .methods = &hal_module_methods,
3779 },
3780};