blob: 4ff1c2334e956f32f216adb7f87036cfb5822721 [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;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301285 pthread_mutex_lock(&out->lock);
1286 out->send_new_metadata = 1;
1287 out->send_next_track_params = true;
1288 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301289 event = STREAM_CBK_EVENT_DRAIN_READY;
1290 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1291 } else
1292 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001293 break;
1294 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001295 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001296 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001297 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001298 send_callback = true;
1299 event = STREAM_CBK_EVENT_DRAIN_READY;
1300 break;
1301 default:
1302 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1303 break;
1304 }
1305 pthread_mutex_lock(&out->lock);
1306 out->offload_thread_blocked = false;
1307 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001308 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001309 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001310 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001311 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 free(cmd);
1313 }
1314
1315 pthread_cond_signal(&out->cond);
1316 while (!list_empty(&out->offload_cmd_list)) {
1317 item = list_head(&out->offload_cmd_list);
1318 list_remove(item);
1319 free(node_to_item(item, struct offload_cmd, node));
1320 }
1321 pthread_mutex_unlock(&out->lock);
1322
1323 return NULL;
1324}
1325
1326static int create_offload_callback_thread(struct stream_out *out)
1327{
1328 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1329 list_init(&out->offload_cmd_list);
1330 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1331 offload_thread_loop, out);
1332 return 0;
1333}
1334
1335static int destroy_offload_callback_thread(struct stream_out *out)
1336{
1337 pthread_mutex_lock(&out->lock);
1338 stop_compressed_output_l(out);
1339 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1340
1341 pthread_mutex_unlock(&out->lock);
1342 pthread_join(out->offload_thread, (void **) NULL);
1343 pthread_cond_destroy(&out->offload_cond);
1344
1345 return 0;
1346}
1347
Eric Laurent07eeafd2013-10-06 12:52:49 -07001348static bool allow_hdmi_channel_config(struct audio_device *adev)
1349{
1350 struct listnode *node;
1351 struct audio_usecase *usecase;
1352 bool ret = true;
1353
1354 list_for_each(node, &adev->usecase_list) {
1355 usecase = node_to_item(node, struct audio_usecase, list);
1356 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1357 /*
1358 * If voice call is already existing, do not proceed further to avoid
1359 * disabling/enabling both RX and TX devices, CSD calls, etc.
1360 * Once the voice call done, the HDMI channels can be configured to
1361 * max channels of remaining use cases.
1362 */
1363 if (usecase->id == USECASE_VOICE_CALL) {
1364 ALOGD("%s: voice call is active, no change in HDMI channels",
1365 __func__);
1366 ret = false;
1367 break;
1368 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1369 ALOGD("%s: multi channel playback is active, "
1370 "no change in HDMI channels", __func__);
1371 ret = false;
1372 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001373 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001374 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001375 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1376 ", no change in HDMI channels", __func__,
1377 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001378 ret = false;
1379 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001380 }
1381 }
1382 }
1383 return ret;
1384}
1385
1386static int check_and_set_hdmi_channels(struct audio_device *adev,
1387 unsigned int channels)
1388{
1389 struct listnode *node;
1390 struct audio_usecase *usecase;
1391
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001392 unsigned int supported_channels = platform_edid_get_max_channels(
1393 adev->platform);
1394 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001395 /* Check if change in HDMI channel config is allowed */
1396 if (!allow_hdmi_channel_config(adev))
1397 return 0;
1398
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001399 if (channels > supported_channels)
1400 channels = supported_channels;
1401
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001403 ALOGD("%s: Requested channels are same as current channels(%d)",
1404 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001405 return 0;
1406 }
1407
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001408 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001409 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001410 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001411 adev->cur_hdmi_channels = channels;
1412
1413 /*
1414 * Deroute all the playback streams routed to HDMI so that
1415 * the back end is deactivated. Note that backend will not
1416 * be deactivated if any one stream is connected to it.
1417 */
1418 list_for_each(node, &adev->usecase_list) {
1419 usecase = node_to_item(node, struct audio_usecase, list);
1420 if (usecase->type == PCM_PLAYBACK &&
1421 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 }
1424 }
1425
1426 /*
1427 * Enable all the streams disabled above. Now the HDMI backend
1428 * will be activated with new channel configuration
1429 */
1430 list_for_each(node, &adev->usecase_list) {
1431 usecase = node_to_item(node, struct audio_usecase, list);
1432 if (usecase->type == PCM_PLAYBACK &&
1433 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001434 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001435 }
1436 }
1437
1438 return 0;
1439}
1440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441static int stop_output_stream(struct stream_out *out)
1442{
1443 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 struct audio_usecase *uc_info;
1445 struct audio_device *adev = out->dev;
1446
Eric Laurent994a6932013-07-17 11:51:42 -07001447 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449 uc_info = get_usecase_from_list(adev, out->usecase);
1450 if (uc_info == NULL) {
1451 ALOGE("%s: Could not find the usecase (%d) in the list",
1452 __func__, out->usecase);
1453 return -EINVAL;
1454 }
1455
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001456 if (is_offload_usecase(out->usecase) &&
1457 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001458 if (adev->visualizer_stop_output != NULL)
1459 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001460
1461 audio_extn_dts_remove_state_notifier_node(out->usecase);
1462
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001463 if (adev->offload_effects_stop_output != NULL)
1464 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1465 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001466
Eric Laurent150dbfe2013-02-27 14:31:02 -08001467 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001468 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001469
1470 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001471 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001473 list_remove(&uc_info->list);
1474 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001476 if (is_offload_usecase(out->usecase) &&
1477 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1478 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1479 ALOGV("Disable passthrough , reset mixer to pcm");
1480 /* NO_PASSTHROUGH */
1481 out->compr_config.codec->compr_passthr = 0;
1482 audio_extn_dolby_set_hdmi_config(adev, out);
1483 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1484 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001485 /* Must be called after removing the usecase from list */
1486 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1487 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1488
Eric Laurent994a6932013-07-17 11:51:42 -07001489 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490 return ret;
1491}
1492
1493int start_output_stream(struct stream_out *out)
1494{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001496 int sink_channels = 0;
1497 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498 struct audio_usecase *uc_info;
1499 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301500 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001502 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1503 ret = -EINVAL;
1504 goto error_config;
1505 }
1506
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301507 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1508 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1509 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301510
Naresh Tanniru80659832014-06-04 18:17:56 +05301511 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301512 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301513 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301514 goto error_config;
1515 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301516
Eric Laurentb23d5282013-05-14 15:27:20 -07001517 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 if (out->pcm_device_id < 0) {
1519 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1520 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001521 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001522 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 }
1524
1525 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001526
1527 if (!uc_info) {
1528 ret = -ENOMEM;
1529 goto error_config;
1530 }
1531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 uc_info->id = out->usecase;
1533 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001534 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 uc_info->devices = out->devices;
1536 uc_info->in_snd_device = SND_DEVICE_NONE;
1537 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001538 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001539 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001540 if (is_offload_usecase(out->usecase)) {
1541 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001542 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1543 }
1544 }
Mingming Yin9c041392014-05-01 15:37:31 -07001545 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1546 if (!strncmp("true", prop_value, 4)) {
1547 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001548 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1549 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001550 check_and_set_hdmi_channels(adev, sink_channels);
1551 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001552 if (is_offload_usecase(out->usecase)) {
1553 unsigned int ch_count = out->compr_config.codec->ch_in;
1554 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1555 /* backend channel config for passthrough stream is stereo */
1556 ch_count = 2;
1557 check_and_set_hdmi_channels(adev, ch_count);
1558 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001559 check_and_set_hdmi_channels(adev, out->config.channels);
1560 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001561 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001562 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001563 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565 select_devices(adev, out->usecase);
1566
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001567 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1568 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001569 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001570 unsigned int flags = PCM_OUT;
1571 unsigned int pcm_open_retry_count = 0;
1572 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1573 flags |= PCM_MMAP | PCM_NOIRQ;
1574 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1575 } else
1576 flags |= PCM_MONOTONIC;
1577
1578 while (1) {
1579 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1580 flags, &out->config);
1581 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1582 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1583 if (out->pcm != NULL) {
1584 pcm_close(out->pcm);
1585 out->pcm = NULL;
1586 }
1587 if (pcm_open_retry_count-- == 0) {
1588 ret = -EIO;
1589 goto error_open;
1590 }
1591 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1592 continue;
1593 }
1594 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001595 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001596 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1597 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001598 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001599 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1600 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001602 out->compr = compress_open(adev->snd_card,
1603 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001604 COMPRESS_IN, &out->compr_config);
1605 if (out->compr && !is_compress_ready(out->compr)) {
1606 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1607 compress_close(out->compr);
1608 out->compr = NULL;
1609 ret = -EIO;
1610 goto error_open;
1611 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301612 /* compress_open sends params of the track, so reset the flag here */
1613 out->is_compr_metadata_avail = false;
1614
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001615 if (out->offload_callback)
1616 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001617
Fred Oh3f43e742015-03-04 18:42:34 -08001618 /* Since small bufs uses blocking writes, a write will be blocked
1619 for the default max poll time (20s) in the event of an SSR.
1620 Reduce the poll time to observe and deal with SSR faster.
1621 */
1622 if (out->use_small_bufs) {
1623 compress_set_max_poll_wait(out->compr, 1000);
1624 }
1625
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001626 audio_extn_dts_create_state_notifier_node(out->usecase);
1627 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1628 popcount(out->channel_mask),
1629 out->playback_started);
1630
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001631#ifdef DS1_DOLBY_DDP_ENABLED
1632 if (audio_extn_is_dolby_format(out->format))
1633 audio_extn_dolby_send_ddp_endp_params(adev);
1634#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001635 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1636 if (adev->visualizer_start_output != NULL)
1637 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1638 if (adev->offload_effects_start_output != NULL)
1639 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001640 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642 }
Eric Laurent994a6932013-07-17 11:51:42 -07001643 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001647error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001648 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649}
1650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651static int check_input_parameters(uint32_t sample_rate,
1652 audio_format_t format,
1653 int channel_count)
1654{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001655 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001657 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001658 !voice_extn_compress_voip_is_format_supported(format) &&
1659 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001660
1661 switch (channel_count) {
1662 case 1:
1663 case 2:
1664 case 6:
1665 break;
1666 default:
1667 ret = -EINVAL;
1668 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669
1670 switch (sample_rate) {
1671 case 8000:
1672 case 11025:
1673 case 12000:
1674 case 16000:
1675 case 22050:
1676 case 24000:
1677 case 32000:
1678 case 44100:
1679 case 48000:
1680 break;
1681 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001682 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683 }
1684
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001685 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001686}
1687
1688static size_t get_input_buffer_size(uint32_t sample_rate,
1689 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001690 int channel_count,
1691 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001692{
1693 size_t size = 0;
1694
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001695 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1696 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001698 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001699 if (is_low_latency)
1700 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001701 /* ToDo: should use frame_size computed based on the format and
1702 channel_count here. */
1703 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001705 /* make sure the size is multiple of 32 bytes
1706 * At 48 kHz mono 16-bit PCM:
1707 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1708 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1709 */
1710 size += 0x1f;
1711 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001712
1713 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714}
1715
1716static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1717{
1718 struct stream_out *out = (struct stream_out *)stream;
1719
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001720 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721}
1722
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001723static int out_set_sample_rate(struct audio_stream *stream __unused,
1724 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725{
1726 return -ENOSYS;
1727}
1728
1729static size_t out_get_buffer_size(const struct audio_stream *stream)
1730{
1731 struct stream_out *out = (struct stream_out *)stream;
1732
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001733 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001734 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001735 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1736 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001738 return out->config.period_size *
1739 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740}
1741
1742static uint32_t out_get_channels(const struct audio_stream *stream)
1743{
1744 struct stream_out *out = (struct stream_out *)stream;
1745
1746 return out->channel_mask;
1747}
1748
1749static audio_format_t out_get_format(const struct audio_stream *stream)
1750{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 struct stream_out *out = (struct stream_out *)stream;
1752
1753 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754}
1755
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001756static int out_set_format(struct audio_stream *stream __unused,
1757 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758{
1759 return -ENOSYS;
1760}
1761
1762static int out_standby(struct audio_stream *stream)
1763{
1764 struct stream_out *out = (struct stream_out *)stream;
1765 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301767 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1768 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001769 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1770 /* Ignore standby in case of voip call because the voip output
1771 * stream is closed in adev_close_output_stream()
1772 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301773 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001774 return 0;
1775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001777 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001779 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001781 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 if (out->pcm) {
1783 pcm_close(out->pcm);
1784 out->pcm = NULL;
1785 }
1786 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001787 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301789 out->send_next_track_params = false;
1790 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001791 out->gapless_mdata.encoder_delay = 0;
1792 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 if (out->compr != NULL) {
1794 compress_close(out->compr);
1795 out->compr = NULL;
1796 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001797 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001799 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 }
1801 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001802 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 return 0;
1804}
1805
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001806static int out_dump(const struct audio_stream *stream __unused,
1807 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808{
1809 return 0;
1810}
1811
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001812static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1813{
1814 int ret = 0;
1815 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001816
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001817 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001818 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001819 return -EINVAL;
1820 }
1821
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001822 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1823 if (ret >= 0) {
1824 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1825 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1826 ALOGV("ADTS format is set in offload mode");
1827 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001828 }
1829
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301830 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001831
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1833 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301834 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1837 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301838 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001839 }
1840
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001841 ALOGV("%s new encoder delay %u and padding %u", __func__,
1842 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1843
1844 return 0;
1845}
1846
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001847static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1848{
1849 return out == adev->primary_output || out == adev->voice_tx_output;
1850}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1853{
1854 struct stream_out *out = (struct stream_out *)stream;
1855 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001856 struct audio_usecase *usecase;
1857 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 struct str_parms *parms;
1859 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001860 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001861 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862
sangwoobc677242013-08-08 16:53:43 +09001863 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001864 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301866 if (!parms)
1867 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001868 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1869 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001872 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301875 * When HDMI cable is unplugged/usb hs is disconnected the
1876 * music playback is paused and the policy manager sends routing=0
1877 * But the audioflingercontinues to write data until standby time
1878 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001879 * Avoid this by routing audio to speaker until standby.
1880 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301881 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1882 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001884 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1885 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001886 }
1887
1888 /*
1889 * select_devices() call below switches all the usecases on the same
1890 * backend to the new device. Refer to check_usecases_codec_backend() in
1891 * the select_devices(). But how do we undo this?
1892 *
1893 * For example, music playback is active on headset (deep-buffer usecase)
1894 * and if we go to ringtones and select a ringtone, low-latency usecase
1895 * will be started on headset+speaker. As we can't enable headset+speaker
1896 * and headset devices at the same time, select_devices() switches the music
1897 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1898 * So when the ringtone playback is completed, how do we undo the same?
1899 *
1900 * We are relying on the out_set_parameters() call on deep-buffer output,
1901 * once the ringtone playback is ended.
1902 * NOTE: We should not check if the current devices are same as new devices.
1903 * Because select_devices() must be called to switch back the music
1904 * playback to headset.
1905 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001906 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001907 out->devices = val;
1908
1909 if (!out->standby)
1910 select_devices(adev, out->usecase);
1911
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001912 if (output_drives_call(adev, out)) {
1913 if(!voice_is_in_call(adev)) {
1914 if (adev->mode == AUDIO_MODE_IN_CALL) {
1915 adev->current_call_output = out;
1916 ret = voice_start_call(adev);
1917 }
1918 } else {
1919 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001920 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001921 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001922 }
1923 }
1924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001926 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001928
1929 if (out == adev->primary_output) {
1930 pthread_mutex_lock(&adev->lock);
1931 audio_extn_set_parameters(adev, parms);
1932 pthread_mutex_unlock(&adev->lock);
1933 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001934 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001935 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001936 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001937
1938 audio_extn_dts_create_state_notifier_node(out->usecase);
1939 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1940 popcount(out->channel_mask),
1941 out->playback_started);
1942
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001943 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001944 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301947error:
Eric Laurent994a6932013-07-17 11:51:42 -07001948 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 return ret;
1950}
1951
1952static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1953{
1954 struct stream_out *out = (struct stream_out *)stream;
1955 struct str_parms *query = str_parms_create_str(keys);
1956 char *str;
1957 char value[256];
1958 struct str_parms *reply = str_parms_create();
1959 size_t i, j;
1960 int ret;
1961 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001962
1963 if (!query || !reply) {
1964 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1965 return NULL;
1966 }
1967
Eric Laurent994a6932013-07-17 11:51:42 -07001968 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1970 if (ret >= 0) {
1971 value[0] = '\0';
1972 i = 0;
1973 while (out->supported_channel_masks[i] != 0) {
1974 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1975 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1976 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001977 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001979 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 first = false;
1981 break;
1982 }
1983 }
1984 i++;
1985 }
1986 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1987 str = str_parms_to_str(reply);
1988 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001989 voice_extn_out_get_parameters(out, query, reply);
1990 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001991 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001992 free(str);
1993 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001994 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001996
1997 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1998 if (ret >= 0) {
1999 value[0] = '\0';
2000 i = 0;
2001 first = true;
2002 while (out->supported_formats[i] != 0) {
2003 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2004 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2005 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002006 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002007 }
2008 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2009 first = false;
2010 break;
2011 }
2012 }
2013 i++;
2014 }
2015 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2016 str = str_parms_to_str(reply);
2017 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018 str_parms_destroy(query);
2019 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002020 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021 return str;
2022}
2023
2024static uint32_t out_get_latency(const struct audio_stream_out *stream)
2025{
2026 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002027 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028
Alexy Josephaa54c872014-12-03 02:46:47 -08002029 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002030 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002031 } else {
2032 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002034 }
2035
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302036 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002037 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038}
2039
2040static int out_set_volume(struct audio_stream_out *stream, float left,
2041 float right)
2042{
Eric Laurenta9024de2013-04-04 09:19:12 -07002043 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 int volume[2];
2045
Eric Laurenta9024de2013-04-04 09:19:12 -07002046 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2047 /* only take left channel into account: the API is for stereo anyway */
2048 out->muted = (left == 0.0f);
2049 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002050 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002051 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2052 /*
2053 * Set mute or umute on HDMI passthrough stream.
2054 * Only take left channel into account.
2055 * Mute is 0 and unmute 1
2056 */
2057 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2058 } else {
2059 char mixer_ctl_name[128];
2060 struct audio_device *adev = out->dev;
2061 struct mixer_ctl *ctl;
2062 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002063 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002065 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2066 "Compress Playback %d Volume", pcm_device_id);
2067 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2068 if (!ctl) {
2069 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2070 __func__, mixer_ctl_name);
2071 return -EINVAL;
2072 }
2073 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2074 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2075 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2076 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002078 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 return -ENOSYS;
2081}
2082
2083static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2084 size_t bytes)
2085{
2086 struct stream_out *out = (struct stream_out *)stream;
2087 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302088 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002089 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302092
Naresh Tanniru80659832014-06-04 18:17:56 +05302093 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002094 // increase written size during SSR to avoid mismatch
2095 // with the written frames count in AF
2096 if (!is_offload_usecase(out->usecase))
2097 out->written += bytes / (out->config.channels * sizeof(short));
2098
Naresh Tanniru80659832014-06-04 18:17:56 +05302099 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302100 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302101 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302102 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002103 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302104 //during SSR for compress usecase we should return error to flinger
2105 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2106 pthread_mutex_unlock(&out->lock);
2107 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302108 }
2109 }
2110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002112 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002113 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002114 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2115 ret = voice_extn_compress_voip_start_output_stream(out);
2116 else
2117 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002118 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002121 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 goto exit;
2123 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302126 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2127 setChannelStatus(out, buffer, bytes);
2128 adev->mChannelStatusSet = true;
2129 }
2130
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002131 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002132 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002133 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002134 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002135 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2136 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302137 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2138 ALOGD("copl(%p):send next track params in gapless", out);
2139 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2140 out->send_next_track_params = false;
2141 out->is_compr_metadata_avail = false;
2142 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002143 }
2144
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302146 if (ret < 0)
2147 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002148 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002149 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302150 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302152 } else if (-ENETRESET == ret) {
2153 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2154 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2155 pthread_mutex_unlock(&out->lock);
2156 out_standby(&out->stream.common);
2157 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302159 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002161 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 out->playback_started = 1;
2163 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002164
2165 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2166 popcount(out->channel_mask),
2167 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 }
2169 pthread_mutex_unlock(&out->lock);
2170 return ret;
2171 } else {
2172 if (out->pcm) {
2173 if (out->muted)
2174 memset((void *)buffer, 0, bytes);
2175 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002176 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2177 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2178 else
2179 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302180 if (ret < 0)
2181 ret = -errno;
2182 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002183 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002184 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 }
2186
2187exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302188 /* ToDo: There may be a corner case when SSR happens back to back during
2189 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302190 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302191 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302192 }
2193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 pthread_mutex_unlock(&out->lock);
2195
2196 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002197 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002198 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302199 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302200 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302201 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302202 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302203 out->standby = true;
2204 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002206 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302207 out_get_sample_rate(&out->stream.common));
2208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 }
2210 return bytes;
2211}
2212
2213static int out_get_render_position(const struct audio_stream_out *stream,
2214 uint32_t *dsp_frames)
2215{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002216 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302217 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002218
2219 if (dsp_frames == NULL)
2220 return -EINVAL;
2221
2222 *dsp_frames = 0;
2223 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002224 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 pthread_mutex_lock(&out->lock);
2226 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302227 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302229 if (ret < 0)
2230 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 ALOGVV("%s rendered frames %d sample_rate %d",
2232 __func__, *dsp_frames, out->sample_rate);
2233 }
2234 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302235 if (-ENETRESET == ret) {
2236 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2237 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2238 return -EINVAL;
2239 } else if(ret < 0) {
2240 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2241 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302242 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2243 /*
2244 * Handle corner case where compress session is closed during SSR
2245 * and timestamp is queried
2246 */
2247 ALOGE(" ERROR: sound card not active, return error");
2248 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302249 } else {
2250 return 0;
2251 }
Zhou Song32a556e2015-05-05 10:46:56 +08002252 } else if (audio_is_linear_pcm(out->format)) {
2253 *dsp_frames = out->written;
2254 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255 } else
2256 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257}
2258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002259static int out_add_audio_effect(const struct audio_stream *stream __unused,
2260 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261{
2262 return 0;
2263}
2264
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002265static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2266 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267{
2268 return 0;
2269}
2270
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002271static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2272 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273{
2274 return -EINVAL;
2275}
2276
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002277static int out_get_presentation_position(const struct audio_stream_out *stream,
2278 uint64_t *frames, struct timespec *timestamp)
2279{
2280 struct stream_out *out = (struct stream_out *)stream;
2281 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002282 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002283
2284 pthread_mutex_lock(&out->lock);
2285
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002286 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002287 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302288 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002289 &out->sample_rate);
2290 ALOGVV("%s rendered frames %ld sample_rate %d",
2291 __func__, dsp_frames, out->sample_rate);
2292 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302293 if (ret < 0)
2294 ret = -errno;
2295 if (-ENETRESET == ret) {
2296 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2297 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2298 ret = -EINVAL;
2299 } else
2300 ret = 0;
2301
Eric Laurent949a0892013-09-20 09:20:13 -07002302 /* this is the best we can do */
2303 clock_gettime(CLOCK_MONOTONIC, timestamp);
2304 }
2305 } else {
2306 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002307 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002308 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2309 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002310 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002311 // This adjustment accounts for buffering after app processor.
2312 // It is based on estimated DSP latency per use case, rather than exact.
2313 signed_frames -=
2314 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2315
Eric Laurent949a0892013-09-20 09:20:13 -07002316 // It would be unusual for this value to be negative, but check just in case ...
2317 if (signed_frames >= 0) {
2318 *frames = signed_frames;
2319 ret = 0;
2320 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002321 }
2322 }
2323 }
2324
2325 pthread_mutex_unlock(&out->lock);
2326
2327 return ret;
2328}
2329
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330static int out_set_callback(struct audio_stream_out *stream,
2331 stream_callback_t callback, void *cookie)
2332{
2333 struct stream_out *out = (struct stream_out *)stream;
2334
2335 ALOGV("%s", __func__);
2336 pthread_mutex_lock(&out->lock);
2337 out->offload_callback = callback;
2338 out->offload_cookie = cookie;
2339 pthread_mutex_unlock(&out->lock);
2340 return 0;
2341}
2342
2343static int out_pause(struct audio_stream_out* stream)
2344{
2345 struct stream_out *out = (struct stream_out *)stream;
2346 int status = -ENOSYS;
2347 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002348 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002349 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002350 pthread_mutex_lock(&out->lock);
2351 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302352 struct audio_device *adev = out->dev;
2353 int snd_scard_state = get_snd_card_state(adev);
2354
2355 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2356 status = compress_pause(out->compr);
2357
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002359
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302360 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002361 audio_extn_dts_notify_playback_state(out->usecase, 0,
2362 out->sample_rate, popcount(out->channel_mask),
2363 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 }
2365 pthread_mutex_unlock(&out->lock);
2366 }
2367 return status;
2368}
2369
2370static int out_resume(struct audio_stream_out* stream)
2371{
2372 struct stream_out *out = (struct stream_out *)stream;
2373 int status = -ENOSYS;
2374 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002375 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002376 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 status = 0;
2378 pthread_mutex_lock(&out->lock);
2379 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302380 struct audio_device *adev = out->dev;
2381 int snd_scard_state = get_snd_card_state(adev);
2382
2383 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2384 status = compress_resume(out->compr);
2385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002387
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302388 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002389 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2390 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 }
2392 pthread_mutex_unlock(&out->lock);
2393 }
2394 return status;
2395}
2396
2397static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2398{
2399 struct stream_out *out = (struct stream_out *)stream;
2400 int status = -ENOSYS;
2401 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002402 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 pthread_mutex_lock(&out->lock);
2404 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2405 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2406 else
2407 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2408 pthread_mutex_unlock(&out->lock);
2409 }
2410 return status;
2411}
2412
2413static int out_flush(struct audio_stream_out* stream)
2414{
2415 struct stream_out *out = (struct stream_out *)stream;
2416 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002417 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002418 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 pthread_mutex_lock(&out->lock);
2420 stop_compressed_output_l(out);
2421 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002422 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 return 0;
2424 }
2425 return -ENOSYS;
2426}
2427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428/** audio_stream_in implementation **/
2429static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2430{
2431 struct stream_in *in = (struct stream_in *)stream;
2432
2433 return in->config.rate;
2434}
2435
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002436static int in_set_sample_rate(struct audio_stream *stream __unused,
2437 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438{
2439 return -ENOSYS;
2440}
2441
2442static size_t in_get_buffer_size(const struct audio_stream *stream)
2443{
2444 struct stream_in *in = (struct stream_in *)stream;
2445
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002446 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2447 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002448 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2449 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002450
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002451 return in->config.period_size *
2452 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453}
2454
2455static uint32_t in_get_channels(const struct audio_stream *stream)
2456{
2457 struct stream_in *in = (struct stream_in *)stream;
2458
2459 return in->channel_mask;
2460}
2461
2462static audio_format_t in_get_format(const struct audio_stream *stream)
2463{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002464 struct stream_in *in = (struct stream_in *)stream;
2465
2466 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467}
2468
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002469static int in_set_format(struct audio_stream *stream __unused,
2470 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471{
2472 return -ENOSYS;
2473}
2474
2475static int in_standby(struct audio_stream *stream)
2476{
2477 struct stream_in *in = (struct stream_in *)stream;
2478 struct audio_device *adev = in->dev;
2479 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302480 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2481 stream, in->usecase, use_case_table[in->usecase]);
2482
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002483 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2484 /* Ignore standby in case of voip call because the voip input
2485 * stream is closed in adev_close_input_stream()
2486 */
2487 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2488 return status;
2489 }
2490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002492 if (!in->standby && in->is_st_session) {
2493 ALOGD("%s: sound trigger pcm stop lab", __func__);
2494 audio_extn_sound_trigger_stop_lab(in);
2495 in->standby = 1;
2496 }
2497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002499 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002501 if (in->pcm) {
2502 pcm_close(in->pcm);
2503 in->pcm = NULL;
2504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002506 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 }
2508 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002509 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 return status;
2511}
2512
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002513static int in_dump(const struct audio_stream *stream __unused,
2514 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515{
2516 return 0;
2517}
2518
2519static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2520{
2521 struct stream_in *in = (struct stream_in *)stream;
2522 struct audio_device *adev = in->dev;
2523 struct str_parms *parms;
2524 char *str;
2525 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002526 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302528 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 parms = str_parms_create_str(kvpairs);
2530
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302531 if (!parms)
2532 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002534 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002535
2536 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2537 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 val = atoi(value);
2539 /* no audio source uses val == 0 */
2540 if ((in->source != val) && (val != 0)) {
2541 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002542 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2543 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2544 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2545 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002546 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002547 err = voice_extn_compress_voip_open_input_stream(in);
2548 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002549 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002550 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002551 }
2552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 }
2554 }
2555
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002556 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2557 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002559 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 in->device = val;
2561 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002562 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002563 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 }
2565 }
2566
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002567done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002569 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570
2571 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302572error:
Eric Laurent994a6932013-07-17 11:51:42 -07002573 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574 return ret;
2575}
2576
2577static char* in_get_parameters(const struct audio_stream *stream,
2578 const char *keys)
2579{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002580 struct stream_in *in = (struct stream_in *)stream;
2581 struct str_parms *query = str_parms_create_str(keys);
2582 char *str;
2583 char value[256];
2584 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002585
2586 if (!query || !reply) {
2587 ALOGE("in_get_parameters: failed to create query or reply");
2588 return NULL;
2589 }
2590
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002591 ALOGV("%s: enter: keys - %s", __func__, keys);
2592
2593 voice_extn_in_get_parameters(in, query, reply);
2594
2595 str = str_parms_to_str(reply);
2596 str_parms_destroy(query);
2597 str_parms_destroy(reply);
2598
2599 ALOGV("%s: exit: returns - %s", __func__, str);
2600 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601}
2602
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002603static int in_set_gain(struct audio_stream_in *stream __unused,
2604 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605{
2606 return 0;
2607}
2608
2609static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2610 size_t bytes)
2611{
2612 struct stream_in *in = (struct stream_in *)stream;
2613 struct audio_device *adev = in->dev;
2614 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302615 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302618
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002619 if (in->is_st_session) {
2620 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2621 /* Read from sound trigger HAL */
2622 audio_extn_sound_trigger_read(in, buffer, bytes);
2623 pthread_mutex_unlock(&in->lock);
2624 return bytes;
2625 }
2626
2627 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2628 ALOGD(" %s: sound card is not active/SSR state", __func__);
2629 ret= -EIO;;
2630 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302631 }
2632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002634 pthread_mutex_lock(&adev->lock);
2635 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2636 ret = voice_extn_compress_voip_start_input_stream(in);
2637 else
2638 ret = start_input_stream(in);
2639 pthread_mutex_unlock(&adev->lock);
2640 if (ret != 0) {
2641 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 }
2643 in->standby = 0;
2644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
2646 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002647 if (audio_extn_ssr_get_enabled() &&
2648 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002649 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002650 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2651 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002652 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2653 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002654 else
2655 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302656 if (ret < 0)
2657 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 }
2659
2660 /*
2661 * Instead of writing zeroes here, we could trust the hardware
2662 * to always provide zeroes when muted.
2663 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302664 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2665 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 memset(buffer, 0, bytes);
2667
2668exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302669 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302670 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002671 if (-ENETRESET == ret)
2672 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 pthread_mutex_unlock(&in->lock);
2675
2676 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302677 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302678 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302679 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302680 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302681 in->standby = true;
2682 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302683 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002685 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002686 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302687 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 }
2689 return bytes;
2690}
2691
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002692static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693{
2694 return 0;
2695}
2696
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002697static int add_remove_audio_effect(const struct audio_stream *stream,
2698 effect_handle_t effect,
2699 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002701 struct stream_in *in = (struct stream_in *)stream;
2702 int status = 0;
2703 effect_descriptor_t desc;
2704
2705 status = (*effect)->get_descriptor(effect, &desc);
2706 if (status != 0)
2707 return status;
2708
2709 pthread_mutex_lock(&in->lock);
2710 pthread_mutex_lock(&in->dev->lock);
2711 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2712 in->enable_aec != enable &&
2713 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2714 in->enable_aec = enable;
2715 if (!in->standby)
2716 select_devices(in->dev, in->usecase);
2717 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002718 if (in->enable_ns != enable &&
2719 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2720 in->enable_ns = enable;
2721 if (!in->standby)
2722 select_devices(in->dev, in->usecase);
2723 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002724 pthread_mutex_unlock(&in->dev->lock);
2725 pthread_mutex_unlock(&in->lock);
2726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 return 0;
2728}
2729
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002730static int in_add_audio_effect(const struct audio_stream *stream,
2731 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732{
Eric Laurent994a6932013-07-17 11:51:42 -07002733 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002734 return add_remove_audio_effect(stream, effect, true);
2735}
2736
2737static int in_remove_audio_effect(const struct audio_stream *stream,
2738 effect_handle_t effect)
2739{
Eric Laurent994a6932013-07-17 11:51:42 -07002740 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002741 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742}
2743
2744static int adev_open_output_stream(struct audio_hw_device *dev,
2745 audio_io_handle_t handle,
2746 audio_devices_t devices,
2747 audio_output_flags_t flags,
2748 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002749 struct audio_stream_out **stream_out,
2750 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751{
2752 struct audio_device *adev = (struct audio_device *)dev;
2753 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002754 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002755 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302758
2759 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2760 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2761 ALOGE(" sound card is not active rejecting compress output open request");
2762 return -EINVAL;
2763 }
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2766
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302767 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2768 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2769 devices, flags, &out->stream);
2770
2771
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002772 if (!out) {
2773 return -ENOMEM;
2774 }
2775
Haynes Mathew George204045b2015-02-25 20:32:03 -08002776 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2777 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 if (devices == AUDIO_DEVICE_NONE)
2780 devices = AUDIO_DEVICE_OUT_SPEAKER;
2781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 out->flags = flags;
2783 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002784 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002785 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002786 out->sample_rate = config->sample_rate;
2787 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2788 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002789 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002790 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002791 out->non_blocking = 0;
2792 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 /* Init use case and pcm_config */
Yamit Mehta29a82082015-07-28 16:08:16 +05302794 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2795 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002796 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2797 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2798
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002800 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2801 ret = read_hdmi_channel_masks(out);
2802
2803 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2804 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002805 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002806 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002807 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002808
2809 if (config->sample_rate == 0)
2810 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2811 if (config->channel_mask == 0)
2812 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2813
2814 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2817 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002819 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002821 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2822 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002823 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002824 ret = voice_extn_compress_voip_open_output_stream(out);
2825 if (ret != 0) {
2826 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2827 __func__, ret);
2828 goto error_open;
2829 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2831 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2832 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2833 ALOGE("%s: Unsupported Offload information", __func__);
2834 ret = -EINVAL;
2835 goto error_open;
2836 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002837
2838 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2839 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2840 ALOGV("read and update_pass through formats");
2841 ret = audio_extn_dolby_update_passt_formats(adev, out);
2842 if(ret != 0) {
2843 goto error_open;
2844 }
2845 if(config->offload_info.format == 0)
2846 config->offload_info.format = out->supported_formats[0];
2847 }
2848
Mingming Yin90310102013-11-13 16:57:00 -08002849 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002850 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851 ALOGE("%s: Unsupported audio format", __func__);
2852 ret = -EINVAL;
2853 goto error_open;
2854 }
2855
2856 out->compr_config.codec = (struct snd_codec *)
2857 calloc(1, sizeof(struct snd_codec));
2858
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002859 if (!out->compr_config.codec) {
2860 ret = -ENOMEM;
2861 goto error_open;
2862 }
2863
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002864 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 if (config->offload_info.channel_mask)
2866 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002867 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002869 config->offload_info.channel_mask = config->channel_mask;
2870 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002871 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 out->sample_rate = config->offload_info.sample_rate;
2873
2874 out->stream.set_callback = out_set_callback;
2875 out->stream.pause = out_pause;
2876 out->stream.resume = out_resume;
2877 out->stream.drain = out_drain;
2878 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002879 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002881 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002882 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002883 audio_extn_dolby_get_snd_codec_id(adev, out,
2884 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002885 else
2886 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 get_snd_codec_id(config->offload_info.format);
Preetam Singh Ranawat3b6927e2015-07-17 17:50:18 +05302888 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD) {
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002889 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002890 platform_get_pcm_offload_buffer_size(&config->offload_info);
2891 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2892 out->compr_config.fragment_size =
2893 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002894 } else {
2895 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002896 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002897 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2899 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002900 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002901 out->compr_config.codec->bit_rate =
2902 config->offload_info.bit_rate;
2903 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002904 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302906 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002907 /*TODO: Do we need to change it for passthrough */
2908 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002909
Mingming Yin3ee55c62014-08-04 14:23:35 -07002910 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2911 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002912 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2913 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002914 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002915 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2916
Mingming Yin3ee55c62014-08-04 14:23:35 -07002917 if (out->bit_width == 24) {
2918 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2919 }
2920
Amit Shekhar6f461b12014-08-01 14:52:58 -07002921 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli4cda5352015-08-12 18:21:25 +05302922 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2925 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002926
Sharad Sangleb27354b2015-06-18 15:58:55 +05302927 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Josephaa54c872014-12-03 02:46:47 -08002928 //this flag is set from framework only if its for PCM formats
2929 //no need to check for PCM format again
2930 out->non_blocking = 0;
2931 out->use_small_bufs = true;
2932 ALOGI("Keep write blocking for small buff: non_blockling %d",
2933 out->non_blocking);
2934 }
2935
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002936 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302937 out->send_next_track_params = false;
2938 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002939 out->offload_state = OFFLOAD_STATE_IDLE;
2940 out->playback_started = 0;
2941
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002942 audio_extn_dts_create_state_notifier_node(out->usecase);
2943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 create_offload_callback_thread(out);
2945 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2946 __func__, config->offload_info.version,
2947 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002948 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002949 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002950 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2951 ret = voice_check_and_set_incall_music_usecase(adev, out);
2952 if (ret != 0) {
2953 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2954 __func__, ret);
2955 goto error_open;
2956 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002957 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2958 if (config->sample_rate == 0)
2959 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2960 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2961 config->sample_rate != 8000) {
2962 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2963 ret = -EINVAL;
2964 goto error_open;
2965 }
2966 out->sample_rate = config->sample_rate;
2967 out->config.rate = config->sample_rate;
2968 if (config->format == AUDIO_FORMAT_DEFAULT)
2969 config->format = AUDIO_FORMAT_PCM_16_BIT;
2970 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2971 config->format = AUDIO_FORMAT_PCM_16_BIT;
2972 ret = -EINVAL;
2973 goto error_open;
2974 }
2975 out->format = config->format;
2976 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2977 out->config = pcm_config_afe_proxy_playback;
2978 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002979 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002980 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2982 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002984 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2985 format = AUDIO_FORMAT_PCM_16_BIT;
2986 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2987 out->config = pcm_config_deep_buffer;
2988 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002989 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002990 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002991 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002992 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002993 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002994 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 }
2996
Amit Shekhar1d896042014-10-03 13:16:09 -07002997 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2998 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002999 /* TODO remove this hardcoding and check why width is zero*/
3000 if (out->bit_width == 0)
3001 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003002 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3003 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003004 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05303005 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003006 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3007 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3008 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003009 if(adev->primary_output == NULL)
3010 adev->primary_output = out;
3011 else {
3012 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003013 ret = -EEXIST;
3014 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003015 }
3016 }
3017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 /* Check if this usecase is already existing */
3019 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003020 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3021 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003024 ret = -EEXIST;
3025 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 }
3027 pthread_mutex_unlock(&adev->lock);
3028
3029 out->stream.common.get_sample_rate = out_get_sample_rate;
3030 out->stream.common.set_sample_rate = out_set_sample_rate;
3031 out->stream.common.get_buffer_size = out_get_buffer_size;
3032 out->stream.common.get_channels = out_get_channels;
3033 out->stream.common.get_format = out_get_format;
3034 out->stream.common.set_format = out_set_format;
3035 out->stream.common.standby = out_standby;
3036 out->stream.common.dump = out_dump;
3037 out->stream.common.set_parameters = out_set_parameters;
3038 out->stream.common.get_parameters = out_get_parameters;
3039 out->stream.common.add_audio_effect = out_add_audio_effect;
3040 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3041 out->stream.get_latency = out_get_latency;
3042 out->stream.set_volume = out_set_volume;
3043 out->stream.write = out_write;
3044 out->stream.get_render_position = out_get_render_position;
3045 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003046 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003049 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051
3052 config->format = out->stream.common.get_format(&out->stream.common);
3053 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3054 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3055
3056 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303057 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3058 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003059
3060 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3061 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3062 popcount(out->channel_mask), out->playback_started);
3063
Eric Laurent994a6932013-07-17 11:51:42 -07003064 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003066
3067error_open:
3068 free(out);
3069 *stream_out = NULL;
3070 ALOGD("%s: exit: ret %d", __func__, ret);
3071 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072}
3073
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003074static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 struct audio_stream_out *stream)
3076{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 struct stream_out *out = (struct stream_out *)stream;
3078 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303081 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3082
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003083 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303084 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003085 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303086 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 if(ret != 0)
3088 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3089 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003090 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003091 out_standby(&stream->common);
3092
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003093 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003094 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003096 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 if (out->compr_config.codec != NULL)
3098 free(out->compr_config.codec);
3099 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003100
3101 if (adev->voice_tx_output == out)
3102 adev->voice_tx_output = NULL;
3103
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003104 pthread_cond_destroy(&out->cond);
3105 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003107 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108}
3109
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003110static void close_compress_sessions(struct audio_device *adev)
3111{
Mingming Yin7b762e72015-03-04 13:47:32 -08003112 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303113 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003114 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003115 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303116
3117 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003118 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303119 if (is_offload_usecase(usecase->id)) {
3120 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003121 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3122 out = usecase->stream.out;
3123 pthread_mutex_unlock(&adev->lock);
3124 out_standby(&out->stream.common);
3125 pthread_mutex_lock(&adev->lock);
3126 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303127 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003128 }
3129 pthread_mutex_unlock(&adev->lock);
3130}
3131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3133{
3134 struct audio_device *adev = (struct audio_device *)dev;
3135 struct str_parms *parms;
3136 char *str;
3137 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003138 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003139 int ret;
3140 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003142 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303145 if (!parms)
3146 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003147 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3148 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303149 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303150 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303151 struct listnode *node;
3152 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303153 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303154 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003155 //close compress sessions on OFFLINE status
3156 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303157 } else if (strstr(snd_card_status, "ONLINE")) {
3158 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303159 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303160 if (!platform_is_acdb_initialized(adev->platform)) {
3161 ret = platform_acdb_init(adev->platform);
3162 if(ret)
3163 ALOGE("acdb initialization is failed");
3164
3165 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303166 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303167 }
3168
3169 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003170 status = voice_set_parameters(adev, parms);
3171 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003172 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003174 status = platform_set_parameters(adev->platform, parms);
3175 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003176 goto done;
3177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3179 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003180 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3182 adev->bluetooth_nrec = true;
3183 else
3184 adev->bluetooth_nrec = false;
3185 }
3186
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003187 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3188 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3190 adev->screen_off = false;
3191 else
3192 adev->screen_off = true;
3193 }
3194
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003195 ret = str_parms_get_int(parms, "rotation", &val);
3196 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 bool reverse_speakers = false;
3198 switch(val) {
3199 // FIXME: note that the code below assumes that the speakers are in the correct placement
3200 // relative to the user when the device is rotated 90deg from its default rotation. This
3201 // assumption is device-specific, not platform-specific like this code.
3202 case 270:
3203 reverse_speakers = true;
3204 break;
3205 case 0:
3206 case 90:
3207 case 180:
3208 break;
3209 default:
3210 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003211 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003212 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003213 if (status == 0) {
3214 if (adev->speaker_lr_swap != reverse_speakers) {
3215 adev->speaker_lr_swap = reverse_speakers;
3216 // only update the selected device if there is active pcm playback
3217 struct audio_usecase *usecase;
3218 struct listnode *node;
3219 list_for_each(node, &adev->usecase_list) {
3220 usecase = node_to_item(node, struct audio_usecase, list);
3221 if (usecase->type == PCM_PLAYBACK) {
3222 select_devices(adev, usecase->id);
3223 break;
3224 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003225 }
3226 }
3227 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003228 }
3229
Mingming Yin514a8bc2014-07-29 15:22:21 -07003230 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3231 if (ret >= 0) {
3232 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3233 adev->bt_wb_speech_enabled = true;
3234 else
3235 adev->bt_wb_speech_enabled = false;
3236 }
3237
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003238 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3239 if (ret >= 0) {
3240 val = atoi(value);
3241 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3242 ALOGV("cache new edid");
3243 platform_cache_edid(adev->platform);
3244 }
3245 }
3246
3247 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3248 if (ret >= 0) {
3249 val = atoi(value);
3250 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3251 ALOGV("invalidate cached edid");
3252 platform_invalidate_edid(adev->platform);
3253 }
3254 }
3255
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003256 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003257
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003258done:
3259 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003260 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303261error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003262 ALOGV("%s: exit with code(%d)", __func__, status);
3263 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264}
3265
3266static char* adev_get_parameters(const struct audio_hw_device *dev,
3267 const char *keys)
3268{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003269 struct audio_device *adev = (struct audio_device *)dev;
3270 struct str_parms *reply = str_parms_create();
3271 struct str_parms *query = str_parms_create_str(keys);
3272 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303273 char value[256] = {0};
3274 int ret = 0;
3275
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003276 if (!query || !reply) {
3277 ALOGE("adev_get_parameters: failed to create query or reply");
3278 return NULL;
3279 }
3280
Naresh Tannirud7205b62014-06-20 02:54:48 +05303281 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3282 sizeof(value));
3283 if (ret >=0) {
3284 int val = 1;
3285 pthread_mutex_lock(&adev->snd_card_status.lock);
3286 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3287 val = 0;
3288 pthread_mutex_unlock(&adev->snd_card_status.lock);
3289 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3290 goto exit;
3291 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003292
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003293 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003294 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003295 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003296 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303297 pthread_mutex_unlock(&adev->lock);
3298
Naresh Tannirud7205b62014-06-20 02:54:48 +05303299exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003300 str = str_parms_to_str(reply);
3301 str_parms_destroy(query);
3302 str_parms_destroy(reply);
3303
3304 ALOGV("%s: exit: returns - %s", __func__, str);
3305 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306}
3307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003308static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309{
3310 return 0;
3311}
3312
3313static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3314{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003315 int ret;
3316 struct audio_device *adev = (struct audio_device *)dev;
3317 pthread_mutex_lock(&adev->lock);
3318 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003319 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003320 pthread_mutex_unlock(&adev->lock);
3321 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322}
3323
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003324static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3325 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326{
3327 return -ENOSYS;
3328}
3329
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003330static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3331 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332{
3333 return -ENOSYS;
3334}
3335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003336static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3337 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338{
3339 return -ENOSYS;
3340}
3341
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003342static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3343 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344{
3345 return -ENOSYS;
3346}
3347
3348static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3349{
3350 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 pthread_mutex_lock(&adev->lock);
3353 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003354 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003356 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3357 voice_is_in_call(adev)) {
3358 voice_stop_call(adev);
Venkata Narendra Kumar Gutta55def542015-06-16 13:59:08 +05303359 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003360 adev->current_call_output = NULL;
3361 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 }
3363 pthread_mutex_unlock(&adev->lock);
3364 return 0;
3365}
3366
3367static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3368{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003369 int ret;
3370
3371 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003372 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003373 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3374 pthread_mutex_unlock(&adev->lock);
3375
3376 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377}
3378
3379static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3380{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003381 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 return 0;
3383}
3384
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003385static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 const struct audio_config *config)
3387{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003388 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003390 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3391 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392}
3393
3394static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003395 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396 audio_devices_t devices,
3397 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003398 struct audio_stream_in **stream_in,
3399 audio_input_flags_t flags __unused,
3400 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003401 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402{
3403 struct audio_device *adev = (struct audio_device *)dev;
3404 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003405 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003406 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003407 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 *stream_in = NULL;
3410 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3411 return -EINVAL;
3412
3413 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003414
3415 if (!in) {
3416 ALOGE("failed to allocate input stream");
3417 return -ENOMEM;
3418 }
3419
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303420 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003421 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3422 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003424 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 in->stream.common.get_sample_rate = in_get_sample_rate;
3427 in->stream.common.set_sample_rate = in_set_sample_rate;
3428 in->stream.common.get_buffer_size = in_get_buffer_size;
3429 in->stream.common.get_channels = in_get_channels;
3430 in->stream.common.get_format = in_get_format;
3431 in->stream.common.set_format = in_set_format;
3432 in->stream.common.standby = in_standby;
3433 in->stream.common.dump = in_dump;
3434 in->stream.common.set_parameters = in_set_parameters;
3435 in->stream.common.get_parameters = in_get_parameters;
3436 in->stream.common.add_audio_effect = in_add_audio_effect;
3437 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3438 in->stream.set_gain = in_set_gain;
3439 in->stream.read = in_read;
3440 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3441
3442 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003443 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 in->standby = 1;
3446 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003447 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448
3449 /* Update config params with the requested sample rate and channels */
3450 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003451 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3452 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3453 is_low_latency = true;
3454#if LOW_LATENCY_CAPTURE_USE_CASE
3455 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3456#endif
3457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003458 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003460 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003461
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003462 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303463 if (adev->mode != AUDIO_MODE_IN_CALL) {
3464 ret = -EINVAL;
3465 goto err_open;
3466 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003467 if (config->sample_rate == 0)
3468 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3469 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3470 config->sample_rate != 8000) {
3471 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3472 ret = -EINVAL;
3473 goto err_open;
3474 }
3475 if (config->format == AUDIO_FORMAT_DEFAULT)
3476 config->format = AUDIO_FORMAT_PCM_16_BIT;
3477 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3478 config->format = AUDIO_FORMAT_PCM_16_BIT;
3479 ret = -EINVAL;
3480 goto err_open;
3481 }
3482
3483 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3484 in->config = pcm_config_afe_proxy_record;
3485 in->config.channels = channel_count;
3486 in->config.rate = config->sample_rate;
3487 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003488 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003489 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003490 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3491 ret = -EINVAL;
3492 goto err_open;
3493 }
3494 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003495 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003496 }
Mingming Yine62d7842013-10-25 16:26:03 -07003497 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003498 audio_extn_compr_cap_format_supported(config->format) &&
3499 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003500 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003501 } else {
3502 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003503 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003504 buffer_size = get_input_buffer_size(config->sample_rate,
3505 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003506 channel_count,
3507 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003508 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003509 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3510 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3511 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3512 (in->config.rate == 8000 || in->config.rate == 16000) &&
3513 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3514 voice_extn_compress_voip_open_input_stream(in);
3515 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003516 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003517
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003518 /* This stream could be for sound trigger lab,
3519 get sound trigger pcm if present */
3520 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303521 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003524 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003525 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526
3527err_open:
3528 free(in);
3529 *stream_in = NULL;
3530 return ret;
3531}
3532
3533static void adev_close_input_stream(struct audio_hw_device *dev,
3534 struct audio_stream_in *stream)
3535{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003536 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003537 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003538 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303539
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303540 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003541
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303542 /* Disable echo reference while closing input stream */
3543 platform_set_echo_reference(adev->platform, false);
3544
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003545 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303546 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003547 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303548 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003549 if (ret != 0)
3550 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3551 __func__, ret);
3552 } else
3553 in_standby(&stream->common);
3554
Mingming Yin7b762e72015-03-04 13:47:32 -08003555 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003556 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003557 audio_extn_ssr_deinit();
3558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559
Mingming Yine62d7842013-10-25 16:26:03 -07003560 if(audio_extn_compr_cap_enabled() &&
3561 audio_extn_compr_cap_format_supported(in->config.format))
3562 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003563
3564 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 return;
3566}
3567
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003568static int adev_dump(const audio_hw_device_t *device __unused,
3569 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570{
3571 return 0;
3572}
3573
3574static int adev_close(hw_device_t *device)
3575{
3576 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003577
3578 if (!adev)
3579 return 0;
3580
3581 pthread_mutex_lock(&adev_init_lock);
3582
3583 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003584 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003585 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003586 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003587 audio_route_free(adev->audio_route);
3588 free(adev->snd_dev_ref_cnt);
3589 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003590 free(device);
3591 adev = NULL;
3592 }
3593 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 return 0;
3595}
3596
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003597/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3598 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3599 * just that it _might_ work.
3600 */
3601static int period_size_is_plausible_for_low_latency(int period_size)
3602{
3603 switch (period_size) {
3604 case 160:
3605 case 240:
3606 case 320:
3607 case 480:
3608 return 1;
3609 default:
3610 return 0;
3611 }
3612}
3613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614static int adev_open(const hw_module_t *module, const char *name,
3615 hw_device_t **device)
3616{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003617 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003619 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3621
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003622 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003623 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003624 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003625 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003626 ALOGD("%s: returning existing instance of adev", __func__);
3627 ALOGD("%s: exit", __func__);
3628 pthread_mutex_unlock(&adev_init_lock);
3629 return 0;
3630 }
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 adev = calloc(1, sizeof(struct audio_device));
3633
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003634 if (!adev) {
3635 pthread_mutex_unlock(&adev_init_lock);
3636 return -ENOMEM;
3637 }
3638
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003639 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3642 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3643 adev->device.common.module = (struct hw_module_t *)module;
3644 adev->device.common.close = adev_close;
3645
3646 adev->device.init_check = adev_init_check;
3647 adev->device.set_voice_volume = adev_set_voice_volume;
3648 adev->device.set_master_volume = adev_set_master_volume;
3649 adev->device.get_master_volume = adev_get_master_volume;
3650 adev->device.set_master_mute = adev_set_master_mute;
3651 adev->device.get_master_mute = adev_get_master_mute;
3652 adev->device.set_mode = adev_set_mode;
3653 adev->device.set_mic_mute = adev_set_mic_mute;
3654 adev->device.get_mic_mute = adev_get_mic_mute;
3655 adev->device.set_parameters = adev_set_parameters;
3656 adev->device.get_parameters = adev_get_parameters;
3657 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3658 adev->device.open_output_stream = adev_open_output_stream;
3659 adev->device.close_output_stream = adev_close_output_stream;
3660 adev->device.open_input_stream = adev_open_input_stream;
3661 adev->device.close_input_stream = adev_close_input_stream;
3662 adev->device.dump = adev_dump;
3663
3664 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003666 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003667 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003670 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003671 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003672 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003673 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003674 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003675 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003676 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303677 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303678
3679 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3680 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003682 adev->platform = platform_init(adev);
3683 if (!adev->platform) {
3684 free(adev->snd_dev_ref_cnt);
3685 free(adev);
3686 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3687 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003688 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003689 return -EINVAL;
3690 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003691
Naresh Tanniru4c630392014-05-12 01:05:52 +05303692 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3693
Eric Laurentc4aef752013-09-12 17:45:53 -07003694 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3695 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3696 if (adev->visualizer_lib == NULL) {
3697 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3698 } else {
3699 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3700 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003701 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003702 "visualizer_hal_start_output");
3703 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003704 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003705 "visualizer_hal_stop_output");
3706 }
3707 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003708 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003709 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003710
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003711 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3712 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3713 if (adev->offload_effects_lib == NULL) {
3714 ALOGE("%s: DLOPEN failed for %s", __func__,
3715 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3716 } else {
3717 ALOGV("%s: DLOPEN successful for %s", __func__,
3718 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3719 adev->offload_effects_start_output =
3720 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3721 "offload_effects_bundle_hal_start_output");
3722 adev->offload_effects_stop_output =
3723 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3724 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003725 adev->offload_effects_set_hpx_state =
3726 (int (*)(bool))dlsym(adev->offload_effects_lib,
3727 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003728 }
3729 }
3730
Mingming Yin514a8bc2014-07-29 15:22:21 -07003731 adev->bt_wb_speech_enabled = false;
3732
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003733 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 *device = &adev->device.common;
3735
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003736 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3737 &adev->streams_output_cfg_list);
3738
Kiran Kandi910e1862013-10-29 13:29:42 -07003739 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003740
3741 char value[PROPERTY_VALUE_MAX];
3742 int trial;
3743 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3744 trial = atoi(value);
3745 if (period_size_is_plausible_for_low_latency(trial)) {
3746 pcm_config_low_latency.period_size = trial;
3747 pcm_config_low_latency.start_threshold = trial / 4;
3748 pcm_config_low_latency.avail_min = trial / 4;
3749 configured_low_latency_capture_period_size = trial;
3750 }
3751 }
3752 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3753 trial = atoi(value);
3754 if (period_size_is_plausible_for_low_latency(trial)) {
3755 configured_low_latency_capture_period_size = trial;
3756 }
3757 }
3758
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003759 pthread_mutex_unlock(&adev_init_lock);
3760
Eric Laurent994a6932013-07-17 11:51:42 -07003761 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762 return 0;
3763}
3764
3765static struct hw_module_methods_t hal_module_methods = {
3766 .open = adev_open,
3767};
3768
3769struct audio_module HAL_MODULE_INFO_SYM = {
3770 .common = {
3771 .tag = HARDWARE_MODULE_TAG,
3772 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3773 .hal_api_version = HARDWARE_HAL_API_VERSION,
3774 .id = AUDIO_HARDWARE_MODULE_ID,
3775 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003776 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 .methods = &hal_module_methods,
3778 },
3779};