blob: 40cb3ea04a451db004a9e3f0394edb01c8a65951 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
39/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070040/*#define VERY_VERY_VERBOSE_LOGGING*/
41#ifdef VERY_VERY_VERBOSE_LOGGING
42#define ALOGVV ALOGV
43#else
44#define ALOGVV(a...) do { } while(0)
45#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080046
47#include <errno.h>
48#include <pthread.h>
49#include <stdint.h>
50#include <sys/time.h>
51#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070053#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070054#include <sys/resource.h>
55#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080056
57#include <cutils/log.h>
58#include <cutils/str_parms.h>
59#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include <cutils/atomic.h>
61#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080062
Eric Laurentb23d5282013-05-14 15:27:20 -070063#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <audio_effects/effect_aec.h>
66#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080067#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include "platform_api.h"
69#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070070#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080071#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080072
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080074#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
77/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080078#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
80
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080083
Mingming Yin08c7e312015-03-16 18:10:58 -070084#ifdef USE_LL_AS_PRIMARY_OUTPUT
85#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
86#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
87#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080088#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070089#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
90#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080091
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurentb23d5282013-05-14 15:27:20 -070095struct pcm_config pcm_config_deep_buffer = {
96 .channels = 2,
97 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
98 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
99 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
100 .format = PCM_FORMAT_S16_LE,
101 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
102 .stop_threshold = INT_MAX,
103 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
104};
105
106struct pcm_config pcm_config_low_latency = {
107 .channels = 2,
108 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
109 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
110 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
111 .format = PCM_FORMAT_S16_LE,
112 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
113 .stop_threshold = INT_MAX,
114 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
115};
116
117struct pcm_config pcm_config_hdmi_multi = {
118 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
119 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
120 .period_size = HDMI_MULTI_PERIOD_SIZE,
121 .period_count = HDMI_MULTI_PERIOD_COUNT,
122 .format = PCM_FORMAT_S16_LE,
123 .start_threshold = 0,
124 .stop_threshold = INT_MAX,
125 .avail_min = 0,
126};
127
128struct pcm_config pcm_config_audio_capture = {
129 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700130 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132};
133
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700134#define AFE_PROXY_CHANNEL_COUNT 2
135#define AFE_PROXY_SAMPLING_RATE 48000
136
137#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
138#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_playback = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
144 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
149};
150
151#define AFE_PROXY_RECORD_PERIOD_SIZE 768
152#define AFE_PROXY_RECORD_PERIOD_COUNT 4
153
154struct pcm_config pcm_config_afe_proxy_record = {
155 .channels = AFE_PROXY_CHANNEL_COUNT,
156 .rate = AFE_PROXY_SAMPLING_RATE,
157 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
158 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
161 .stop_threshold = INT_MAX,
162 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
163};
164
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800165const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
167 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
168 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700169 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700170#ifdef MULTIPLE_OFFLOAD_ENABLED
171 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
172 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
173 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
174 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
175 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
176 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
177 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
178 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
179#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700181 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700182 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700183 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700184 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800185 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800186 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700187 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700188
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700189 [USECASE_VOICE2_CALL] = "voice2-call",
190 [USECASE_VOLTE_CALL] = "volte-call",
191 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800192 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800193 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
194 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800195 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700196 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
197 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
198 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800199 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
200 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
201 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
202
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700203 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
204 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700205 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
206 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700207
208 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
209 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700210};
211
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700212static const audio_usecase_t offload_usecases[] = {
213 USECASE_AUDIO_PLAYBACK_OFFLOAD,
214#ifdef MULTIPLE_OFFLOAD_ENABLED
215 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
216 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
217 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
218 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
219 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
220 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
221 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
222 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
223#endif
224};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800225
226#define STRING_TO_ENUM(string) { #string, string }
227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800228struct string_to_enum {
229 const char *name;
230 uint32_t value;
231};
232
233static const struct string_to_enum out_channels_name_to_enum_table[] = {
234 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700235 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),/* QUAD_BACK is same as QUAD */
236 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD_SIDE),
237 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
238 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), /* 5POINT1_BACK is same as 5POINT1 */
239 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800240 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
241};
242
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700243static const struct string_to_enum out_formats_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
245 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
246 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
247};
248
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700249static struct audio_device *adev = NULL;
250static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700251static unsigned int audio_device_ref_count;
252
Haynes Mathew George5191a852013-09-11 14:19:36 -0700253static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800254
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800255static int check_and_set_gapless_mode(struct audio_device *adev) {
256
257
258 char value[PROPERTY_VALUE_MAX] = {0};
259 bool gapless_enabled = false;
260 const char *mixer_ctl_name = "Compress Gapless Playback";
261 struct mixer_ctl *ctl;
262
263 ALOGV("%s:", __func__);
264 property_get("audio.offload.gapless.enabled", value, NULL);
265 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
266
267 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
268 if (!ctl) {
269 ALOGE("%s: Could not get ctl for mixer cmd - %s",
270 __func__, mixer_ctl_name);
271 return -EINVAL;
272 }
273
274 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
275 ALOGE("%s: Could not set gapless mode %d",
276 __func__, gapless_enabled);
277 return -EINVAL;
278 }
279 return 0;
280}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700281
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700282static bool is_supported_format(audio_format_t format)
283{
Eric Laurent86e17132013-09-12 17:49:30 -0700284 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530285 format == AUDIO_FORMAT_AAC_LC ||
286 format == AUDIO_FORMAT_AAC_HE_V1 ||
287 format == AUDIO_FORMAT_AAC_HE_V2 ||
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800288 format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
Mingming Yin3ee55c62014-08-04 14:23:35 -0700289 format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800290 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530291 format == AUDIO_FORMAT_ALAC ||
292 format == AUDIO_FORMAT_APE ||
293 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800294 format == AUDIO_FORMAT_WMA ||
295 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800296 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700297
298 return false;
299}
300
301static int get_snd_codec_id(audio_format_t format)
302{
303 int id = 0;
304
Ashish Jainf9b78162014-08-25 20:36:25 +0530305 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700306 case AUDIO_FORMAT_MP3:
307 id = SND_AUDIOCODEC_MP3;
308 break;
309 case AUDIO_FORMAT_AAC:
310 id = SND_AUDIOCODEC_AAC;
311 break;
Ashish Jainf9b78162014-08-25 20:36:25 +0530312 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800313 id = SND_AUDIOCODEC_PCM;
314 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700315 case AUDIO_FORMAT_FLAC:
316 id = SND_AUDIOCODEC_FLAC;
317 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530318 case AUDIO_FORMAT_ALAC:
319 id = SND_AUDIOCODEC_ALAC;
320 break;
321 case AUDIO_FORMAT_APE:
322 id = SND_AUDIOCODEC_APE;
323 break;
324 case AUDIO_FORMAT_VORBIS:
325 id = SND_AUDIOCODEC_VORBIS;
326 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800327 case AUDIO_FORMAT_WMA:
328 id = SND_AUDIOCODEC_WMA;
329 break;
330 case AUDIO_FORMAT_WMA_PRO:
331 id = SND_AUDIOCODEC_WMA_PRO;
332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700333 default:
Mingming Yin90310102013-11-13 16:57:00 -0800334 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700335 }
336
337 return id;
338}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800339
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530340int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530341{
342 int snd_scard_state;
343
344 if (!adev)
345 return SND_CARD_STATE_OFFLINE;
346
347 pthread_mutex_lock(&adev->snd_card_status.lock);
348 snd_scard_state = adev->snd_card_status.state;
349 pthread_mutex_unlock(&adev->snd_card_status.lock);
350
351 return snd_scard_state;
352}
353
354static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
355{
356 if (!adev)
357 return -ENOSYS;
358
359 pthread_mutex_lock(&adev->snd_card_status.lock);
360 adev->snd_card_status.state = snd_scard_state;
361 pthread_mutex_unlock(&adev->snd_card_status.lock);
362
363 return 0;
364}
365
Avinash Vaish71a8b972014-07-24 15:36:33 +0530366static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
367 struct audio_usecase *uc_info)
368{
369 struct listnode *node;
370 struct audio_usecase *usecase;
371
372 if (uc_info == NULL)
373 return -EINVAL;
374
375 /* Re-route all voice usecases on the shared backend other than the
376 specified usecase to new snd devices */
377 list_for_each(node, &adev->usecase_list) {
378 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800379 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530380 enable_audio_route(adev, usecase);
381 }
382 return 0;
383}
384
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700385int pcm_ioctl(struct pcm *pcm, int request, ...)
386{
387 va_list ap;
388 void * arg;
389 int pcm_fd = *(int*)pcm;
390
391 va_start(ap, request);
392 arg = va_arg(ap, void *);
393 va_end(ap);
394
395 return ioctl(pcm_fd, request, arg);
396}
397
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700398int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700399 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800400{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700402 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800403
404 if (usecase == NULL)
405 return -EINVAL;
406
407 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
408
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800409 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700410 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800411 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700412 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800414#ifdef DS1_DOLBY_DAP_ENABLED
415 audio_extn_dolby_set_dmid(adev);
416 audio_extn_dolby_set_endpoint(adev);
417#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700418 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700419 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530420 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700421 audio_extn_utils_send_audio_calibration(adev, usecase);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -0700422 audio_extn_utils_send_app_type_cfg(usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800423 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700424 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700425 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
426 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427 ALOGV("%s: exit", __func__);
428 return 0;
429}
430
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700431int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700435 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530437 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700441 if (usecase->type == PCM_CAPTURE)
442 snd_device = usecase->in_snd_device;
443 else
444 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800445 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Eric Laurentb23d5282013-05-14 15:27:20 -0700446 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700447 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
448 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700449 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530450 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800451 ALOGV("%s: exit", __func__);
452 return 0;
453}
454
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700455int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700456 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800457{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700458 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
459
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800460 if (snd_device < SND_DEVICE_MIN ||
461 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800462 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800463 return -EINVAL;
464 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700465
466 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700467
468 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
469 ALOGE("%s: Invalid sound device returned", __func__);
470 return -EINVAL;
471 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700472 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700474 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700475 return 0;
476 }
477
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700478 if (audio_extn_spkr_prot_is_enabled())
479 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700480 /* start usb playback thread */
481 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
482 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
483 audio_extn_usb_start_playback(adev);
484
485 /* start usb capture thread */
486 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
487 audio_extn_usb_start_capture(adev);
488
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530489 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800490 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700491 audio_extn_spkr_prot_is_enabled()) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700492 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
493 adev->snd_dev_ref_cnt[snd_device]--;
494 return -EINVAL;
495 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200496 audio_extn_dev_arbi_acquire(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800497 if (audio_extn_spkr_prot_start_processing(snd_device)) {
498 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200499 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800500 return -EINVAL;
501 }
502 } else {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700503 ALOGV("%s: snd_device(%d: %s)", __func__,
504 snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700505 /* due to the possibility of calibration overwrite between listen
506 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700507 audio_extn_sound_trigger_update_device_status(snd_device,
508 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530509 audio_extn_listen_update_device_status(snd_device,
510 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700511 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700512 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700513 audio_extn_sound_trigger_update_device_status(snd_device,
514 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530515 audio_extn_listen_update_device_status(snd_device,
516 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700517 return -EINVAL;
518 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300519 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700520 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522 return 0;
523}
524
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700526 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700528 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
529
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800530 if (snd_device < SND_DEVICE_MIN ||
531 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800532 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800533 return -EINVAL;
534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700535 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
536 ALOGE("%s: device ref cnt is already 0", __func__);
537 return -EINVAL;
538 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700539
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700541
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700542 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
543 ALOGE("%s: Invalid sound device returned", __func__);
544 return -EINVAL;
545 }
546
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700548 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700549 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800550 /* exit usb play back thread */
551 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
552 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
553 audio_extn_usb_stop_playback();
554
555 /* exit usb capture thread */
556 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -0700557 audio_extn_usb_stop_capture();
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800558
Laxminath Kasambe641ab2015-07-24 20:27:42 +0530559 if ((snd_device == SND_DEVICE_OUT_SPEAKER || snd_device == SND_DEVICE_OUT_SPEAKER_WSA ||
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700562 audio_extn_spkr_prot_stop_processing(snd_device);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300563 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700564 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300565 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700566
Ashish Jain5a97ddd2015-05-13 10:52:34 +0530567 if (snd_device == SND_DEVICE_OUT_HDMI)
568 adev->mChannelStatusSet = false;
569
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200570 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700571 audio_extn_sound_trigger_update_device_status(snd_device,
572 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530573 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800574 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577 return 0;
578}
579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580static void check_usecases_codec_backend(struct audio_device *adev,
581 struct audio_usecase *uc_info,
582 snd_device_t snd_device)
583{
584 struct listnode *node;
585 struct audio_usecase *usecase;
586 bool switch_device[AUDIO_USECASE_MAX];
587 int i, num_uc_to_switch = 0;
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530588 int backend_idx = DEFAULT_CODEC_BACKEND;
589 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700590
591 /*
592 * This function is to make sure that all the usecases that are active on
593 * the hardware codec backend are always routed to any one device that is
594 * handled by the hardware codec.
595 * For example, if low-latency and deep-buffer usecases are currently active
596 * on speaker and out_set_parameters(headset) is received on low-latency
597 * output, then we have to make sure deep-buffer is also switched to headset,
598 * because of the limitation that both the devices cannot be enabled
599 * at the same time as they share the same backend.
600 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700601 /*
602 * This call is to check if we need to force routing for a particular stream
603 * If there is a backend configuration change for the device when a
604 * new stream starts, then ADM needs to be closed and re-opened with the new
605 * configuraion. This call check if we need to re-route all the streams
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530606 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700607 */
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530608 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
609 snd_device);
610 backend_idx = platform_get_backend_index(snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611 /* Disable all the usecases on the shared backend other than the
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800612 * specified usecase.
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800613 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 for (i = 0; i < AUDIO_USECASE_MAX; i++)
615 switch_device[i] = false;
616
617 list_for_each(node, &adev->usecase_list) {
618 usecase = node_to_item(node, struct audio_usecase, list);
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530619
620 if (usecase == uc_info)
621 continue;
622 usecase_backend_idx = platform_get_backend_index(usecase->out_snd_device);
623 ALOGV("%s: backend_idx: %d,"
624 "usecase_backend_idx: %d, curr device: %s, usecase device:"
625 "%s", __func__, backend_idx, usecase_backend_idx, platform_get_snd_device_name(snd_device),
Preetam Singh Ranawatb28f2e52015-06-18 23:20:28 +0530626 platform_get_snd_device_name(usecase->out_snd_device));
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530627
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800628 if (usecase->type != PCM_CAPTURE &&
Mingming Yin3ee55c62014-08-04 14:23:35 -0700629 (usecase->out_snd_device != snd_device || force_routing) &&
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530630 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
631 usecase_backend_idx == backend_idx) {
Sidipotu Ashokce33cdc2015-07-06 18:35:03 +0530632 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..", __func__,
Preetam Singh Ranawat36f3d372015-06-18 22:59:53 +0530633 use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700634 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700635 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700636 switch_device[usecase->id] = true;
637 num_uc_to_switch++;
638 }
639 }
640
641 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700642 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700643
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530644 /* Make sure the previous devices to be disabled first and then enable the
645 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 list_for_each(node, &adev->usecase_list) {
647 usecase = node_to_item(node, struct audio_usecase, list);
648 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700649 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 }
651 }
652
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700653 list_for_each(node, &adev->usecase_list) {
654 usecase = node_to_item(node, struct audio_usecase, list);
655 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700656 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700657 }
658 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700659
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 /* Re-route all the usecases on the shared backend other than the
661 specified usecase to new snd devices */
662 list_for_each(node, &adev->usecase_list) {
663 usecase = node_to_item(node, struct audio_usecase, list);
Venkata Narendra Kumar Gutta7a237892015-08-04 14:45:37 +0530664 /* Update the out_snd_device only for the usecases that are enabled here */
665 if (switch_device[usecase->id] && (usecase->type != VOICE_CALL)) {
666 usecase->out_snd_device = snd_device;
Avinash Vaish71a8b972014-07-24 15:36:33 +0530667 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 }
669 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700670 }
671}
672
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700673static void check_and_route_capture_usecases(struct audio_device *adev,
674 struct audio_usecase *uc_info,
675 snd_device_t snd_device)
676{
677 struct listnode *node;
678 struct audio_usecase *usecase;
679 bool switch_device[AUDIO_USECASE_MAX];
680 int i, num_uc_to_switch = 0;
681
682 /*
683 * This function is to make sure that all the active capture usecases
684 * are always routed to the same input sound device.
685 * For example, if audio-record and voice-call usecases are currently
686 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
687 * is received for voice call then we have to make sure that audio-record
688 * usecase is also switched to earpiece i.e. voice-dmic-ef,
689 * because of the limitation that two devices cannot be enabled
690 * at the same time if they share the same backend.
691 */
692 for (i = 0; i < AUDIO_USECASE_MAX; i++)
693 switch_device[i] = false;
694
695 list_for_each(node, &adev->usecase_list) {
696 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800697 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700698 usecase != uc_info &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700699 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella81491ba2015-07-08 19:38:38 -0700700 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
701 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700702 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700703 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
704 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700705 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700706 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700707 switch_device[usecase->id] = true;
708 num_uc_to_switch++;
709 }
710 }
711
712 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700713 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700714
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530715 /* Make sure the previous devices to be disabled first and then enable the
716 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700717 list_for_each(node, &adev->usecase_list) {
718 usecase = node_to_item(node, struct audio_usecase, list);
719 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700720 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800721 }
722 }
723
724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
726 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700728 }
729 }
730
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700731 /* Re-route all the usecases on the shared backend other than the
732 specified usecase to new snd devices */
733 list_for_each(node, &adev->usecase_list) {
734 usecase = node_to_item(node, struct audio_usecase, list);
735 /* Update the in_snd_device only before enabling the audio route */
736 if (switch_device[usecase->id] ) {
737 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800738 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530739 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700740 }
741 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742 }
743}
744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800745/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700746static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747{
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700748 int ret = 0, i = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700749 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750
751 switch (channels) {
752 /*
753 * Do not handle stereo output in Multi-channel cases
754 * Stereo case is handled in normal playback path
755 */
756 case 6:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700757 ALOGV("%s: HDMI supports Quad and 5.1", __func__);
758 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
759 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
760 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
761 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
762 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763 break;
764 case 8:
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700765 ALOGV("%s: HDMI supports Quad, 5.1 and 7.1 channels", __func__);
766 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
767 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD_SIDE;
768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
769 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1_SIDE;
771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772 break;
773 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700774 ALOGE("HDMI does not support multi channel playback");
775 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 break;
777 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700778 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779}
780
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800781audio_usecase_t get_usecase_id_from_usecase_type(struct audio_device *adev,
782 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700783{
784 struct audio_usecase *usecase;
785 struct listnode *node;
786
787 list_for_each(node, &adev->usecase_list) {
788 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800789 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700790 ALOGV("%s: usecase id %d", __func__, usecase->id);
791 return usecase->id;
792 }
793 }
794 return USECASE_INVALID;
795}
796
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700797struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700798 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799{
800 struct audio_usecase *usecase;
801 struct listnode *node;
802
803 list_for_each(node, &adev->usecase_list) {
804 usecase = node_to_item(node, struct audio_usecase, list);
805 if (usecase->id == uc_id)
806 return usecase;
807 }
808 return NULL;
809}
810
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700811int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800813 snd_device_t out_snd_device = SND_DEVICE_NONE;
814 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 struct audio_usecase *usecase = NULL;
816 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800817 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800818 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800819 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800820 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 usecase = get_usecase_from_list(adev, uc_id);
824 if (usecase == NULL) {
825 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
826 return -EINVAL;
827 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800828
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800829 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800830 (usecase->type == VOIP_CALL) ||
831 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700832 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800833 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -0700834 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835 usecase->devices = usecase->stream.out->devices;
836 } else {
837 /*
838 * If the voice call is active, use the sound devices of voice call usecase
839 * so that it would not result any device switch. All the usecases will
840 * be switched to new device when select_devices() is called for voice call
841 * usecase. This is to avoid switching devices for voice call when
842 * check_usecases_codec_backend() is called below.
843 */
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700844 if (voice_is_in_call(adev) && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700845 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -0800846 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700847 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
848 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849 in_snd_device = vc_usecase->in_snd_device;
850 out_snd_device = vc_usecase->out_snd_device;
851 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800852 } else if (voice_extn_compress_voip_is_active(adev)) {
853 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700854 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +0530855 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700856 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800857 in_snd_device = voip_usecase->in_snd_device;
858 out_snd_device = voip_usecase->out_snd_device;
859 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800860 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -0800861 hfp_ucid = audio_extn_hfp_get_usecase();
862 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -0700863 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800864 in_snd_device = hfp_usecase->in_snd_device;
865 out_snd_device = hfp_usecase->out_snd_device;
866 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 }
868 if (usecase->type == PCM_PLAYBACK) {
869 usecase->devices = usecase->stream.out->devices;
870 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700871 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700872 out_snd_device = platform_get_output_snd_device(adev->platform,
Preetam Singh Ranawat1871ddb2015-02-18 12:23:23 -0800873 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700874 if (usecase->stream.out == adev->primary_output &&
875 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800876 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700877 select_devices(adev, adev->active_input->usecase);
878 }
879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 } else if (usecase->type == PCM_CAPTURE) {
881 usecase->devices = usecase->stream.in->device;
882 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700883 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700884 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +0530885 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
886 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
887 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
888 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700889 out_device = adev->primary_output->devices;
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -0800890 platform_set_echo_reference(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700891 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
892 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700893 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700894 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700895 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 }
897 }
898
899 if (out_snd_device == usecase->out_snd_device &&
900 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800901 return 0;
902 }
903
sangwoobc677242013-08-08 16:53:43 +0900904 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700905 out_snd_device, platform_get_snd_device_name(out_snd_device),
906 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800908 /*
909 * Limitation: While in call, to do a device switch we need to disable
910 * and enable both RX and TX devices though one of them is same as current
911 * device.
912 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700913 if ((usecase->type == VOICE_CALL) &&
914 (usecase->in_snd_device != SND_DEVICE_NONE) &&
915 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700916 status = platform_switch_voice_call_device_pre(adev->platform);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700917 /* Disable sidetone only if voice call already exists */
918 if (voice_is_call_state_active(adev))
919 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800920 }
921
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 /* Disable current sound devices */
923 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700924 disable_audio_route(adev, usecase);
925 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800926 }
927
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700929 disable_audio_route(adev, usecase);
930 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800931 }
932
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800933 /* Applicable only on the targets that has external modem.
934 * New device information should be sent to modem before enabling
935 * the devices to reduce in-call device switch time.
936 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700937 if ((usecase->type == VOICE_CALL) &&
938 (usecase->in_snd_device != SND_DEVICE_NONE) &&
939 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800940 status = platform_switch_voice_call_enable_device_config(adev->platform,
941 out_snd_device,
942 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -0700943 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -0800944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 /* Enable new sound devices */
946 if (out_snd_device != SND_DEVICE_NONE) {
947 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
948 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700949 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800950 }
951
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 if (in_snd_device != SND_DEVICE_NONE) {
953 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700954 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956
Avinash Vaish71a8b972014-07-24 15:36:33 +0530957 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700958 status = platform_switch_voice_call_device_post(adev->platform,
959 out_snd_device,
960 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530961 enable_audio_route_for_voice_usecases(adev, usecase);
Bhalchandra Gajarefd72d3e2015-06-09 22:23:45 -0700962 /* Enable sidetone only if voice call already exists */
963 if (voice_is_call_state_active(adev))
964 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +0530965 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800966
sangwoo170731f2013-06-08 15:36:36 +0900967 usecase->in_snd_device = in_snd_device;
968 usecase->out_snd_device = out_snd_device;
969
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530970 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -0700971 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530972 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -0700973 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530974 usecase->stream.out->flags,
975 usecase->stream.out->format,
976 usecase->stream.out->sample_rate,
977 usecase->stream.out->bit_width,
978 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -0700979 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +0530980 }
Amit Shekhar1d896042014-10-03 13:16:09 -0700981
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700982 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900983
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800984 /* Applicable only on the targets that has external modem.
985 * Enable device command should be sent to modem only after
986 * enabling voice call mixer controls
987 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -0700988 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800989 status = platform_switch_voice_call_usecase_route_post(adev->platform,
990 out_snd_device,
991 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +0530992 ALOGD("%s: done",__func__);
993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 return status;
995}
996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997static int stop_input_stream(struct stream_in *in)
998{
999 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000 struct audio_usecase *uc_info;
1001 struct audio_device *adev = in->dev;
1002
Eric Laurentc8400632013-02-14 19:04:54 -08001003 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004
Eric Laurent994a6932013-07-17 11:51:42 -07001005 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001006 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 uc_info = get_usecase_from_list(adev, in->usecase);
1008 if (uc_info == NULL) {
1009 ALOGE("%s: Could not find the usecase (%d) in the list",
1010 __func__, in->usecase);
1011 return -EINVAL;
1012 }
1013
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001014 /* Close in-call recording streams */
1015 voice_check_and_stop_incall_rec_usecase(adev, in);
1016
Eric Laurent150dbfe2013-02-27 14:31:02 -08001017 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001018 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019
1020 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001021 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001023 list_remove(&uc_info->list);
1024 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Eric Laurent994a6932013-07-17 11:51:42 -07001026 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 return ret;
1028}
1029
1030int start_input_stream(struct stream_in *in)
1031{
1032 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001033 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 struct audio_usecase *uc_info;
1035 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301036 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037
Mingming Yine62d7842013-10-25 16:26:03 -07001038 in->usecase = platform_update_usecase_from_source(in->source,in->usecase);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301039 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1040 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001041
Naresh Tanniru80659832014-06-04 18:17:56 +05301042
1043 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301044 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301045 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301046 goto error_config;
1047 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301048
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001049 /* Check if source matches incall recording usecase criteria */
1050 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1051 if (ret)
1052 goto error_config;
1053 else
Narsinga Rao Chella212e2542014-11-17 19:57:04 -08001054 ALOGD("%s: Updated usecase(%d: %s)",
1055 __func__, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001056
Eric Laurentb23d5282013-05-14 15:27:20 -07001057 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 if (in->pcm_device_id < 0) {
1059 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1060 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001061 ret = -EINVAL;
1062 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001064
1065 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001067
1068 if (!uc_info) {
1069 ret = -ENOMEM;
1070 goto error_config;
1071 }
1072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001073 uc_info->id = in->usecase;
1074 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001075 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001076 uc_info->devices = in->device;
1077 uc_info->in_snd_device = SND_DEVICE_NONE;
1078 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001079
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001080 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301081 audio_extn_perf_lock_acquire();
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083
Eric Laurentc8400632013-02-14 19:04:54 -08001084 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001085 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1086
1087 unsigned int flags = PCM_IN;
1088 unsigned int pcm_open_retry_count = 0;
1089
1090 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1091 flags |= PCM_MMAP | PCM_NOIRQ;
1092 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1093 }
1094
1095 while (1) {
1096 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1097 flags, &in->config);
1098 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1099 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1100 if (in->pcm != NULL) {
1101 pcm_close(in->pcm);
1102 in->pcm = NULL;
1103 }
1104 if (pcm_open_retry_count-- == 0) {
1105 ret = -EIO;
1106 goto error_open;
1107 }
1108 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1109 continue;
1110 }
1111 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 }
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301113 audio_extn_perf_lock_release();
Naresh Tanniru4c630392014-05-12 01:05:52 +05301114
Eric Laurent994a6932013-07-17 11:51:42 -07001115 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001116 return ret;
1117
1118error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119 stop_input_stream(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05301120 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001121
1122error_config:
1123 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001125
1126 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127}
1128
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001129/* must be called with out->lock locked */
1130static int send_offload_cmd_l(struct stream_out* out, int command)
1131{
1132 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1133
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001134 if (!cmd) {
1135 ALOGE("failed to allocate mem for command 0x%x", command);
1136 return -ENOMEM;
1137 }
1138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001139 ALOGVV("%s %d", __func__, command);
1140
1141 cmd->cmd = command;
1142 list_add_tail(&out->offload_cmd_list, &cmd->node);
1143 pthread_cond_signal(&out->offload_cond);
1144 return 0;
1145}
1146
1147/* must be called iwth out->lock locked */
1148static void stop_compressed_output_l(struct stream_out *out)
1149{
1150 out->offload_state = OFFLOAD_STATE_IDLE;
1151 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001152 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001153 if (out->compr != NULL) {
1154 compress_stop(out->compr);
1155 while (out->offload_thread_blocked) {
1156 pthread_cond_wait(&out->cond, &out->lock);
1157 }
1158 }
1159}
1160
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001161bool is_offload_usecase(audio_usecase_t uc_id)
1162{
1163 unsigned int i;
1164 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1165 if (uc_id == offload_usecases[i])
1166 return true;
1167 }
1168 return false;
1169}
1170
1171static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1172{
1173 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1174 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1175 char value[PROPERTY_VALUE_MAX] = {0};
1176
1177 property_get("audio.offload.multiple.enabled", value, NULL);
1178 if (!(atoi(value) || !strncmp("true", value, 4)))
1179 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1180
1181 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1182 for (i = 0; i < num_usecase; i++) {
1183 if (!(adev->offload_usecases_state & (0x1<<i))) {
1184 adev->offload_usecases_state |= 0x1 << i;
1185 ret = offload_usecases[i];
1186 break;
1187 }
1188 }
1189 ALOGV("%s: offload usecase is %d", __func__, ret);
1190 return ret;
1191}
1192
1193static void free_offload_usecase(struct audio_device *adev,
1194 audio_usecase_t uc_id)
1195{
1196 unsigned int i;
1197 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1198 if (offload_usecases[i] == uc_id) {
1199 adev->offload_usecases_state &= ~(0x1<<i);
1200 break;
1201 }
1202 }
1203 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1204}
1205
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001206static void *offload_thread_loop(void *context)
1207{
1208 struct stream_out *out = (struct stream_out *) context;
1209 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001210 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001211
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001212 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1213 set_sched_policy(0, SP_FOREGROUND);
1214 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1215
1216 ALOGV("%s", __func__);
1217 pthread_mutex_lock(&out->lock);
1218 for (;;) {
1219 struct offload_cmd *cmd = NULL;
1220 stream_callback_event_t event;
1221 bool send_callback = false;
1222
1223 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1224 __func__, list_empty(&out->offload_cmd_list),
1225 out->offload_state);
1226 if (list_empty(&out->offload_cmd_list)) {
1227 ALOGV("%s SLEEPING", __func__);
1228 pthread_cond_wait(&out->offload_cond, &out->lock);
1229 ALOGV("%s RUNNING", __func__);
1230 continue;
1231 }
1232
1233 item = list_head(&out->offload_cmd_list);
1234 cmd = node_to_item(item, struct offload_cmd, node);
1235 list_remove(item);
1236
1237 ALOGVV("%s STATE %d CMD %d out->compr %p",
1238 __func__, out->offload_state, cmd->cmd, out->compr);
1239
1240 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1241 free(cmd);
1242 break;
1243 }
1244
1245 if (out->compr == NULL) {
1246 ALOGE("%s: Compress handle is NULL", __func__);
1247 pthread_cond_signal(&out->cond);
1248 continue;
1249 }
1250 out->offload_thread_blocked = true;
1251 pthread_mutex_unlock(&out->lock);
1252 send_callback = false;
1253 switch(cmd->cmd) {
1254 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001255 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001256 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001257 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001258 send_callback = true;
1259 event = STREAM_CBK_EVENT_WRITE_READY;
1260 break;
1261 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001262 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301263 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001264 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301265 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001266 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301267 if (ret < 0)
1268 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301269 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301270 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001271 compress_drain(out->compr);
1272 else
1273 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301274 if (ret != -ENETRESET) {
1275 send_callback = true;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301276 pthread_mutex_lock(&out->lock);
1277 out->send_new_metadata = 1;
1278 out->send_next_track_params = true;
1279 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301280 event = STREAM_CBK_EVENT_DRAIN_READY;
1281 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1282 } else
1283 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001284 break;
1285 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001286 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001287 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001288 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 send_callback = true;
1290 event = STREAM_CBK_EVENT_DRAIN_READY;
1291 break;
1292 default:
1293 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1294 break;
1295 }
1296 pthread_mutex_lock(&out->lock);
1297 out->offload_thread_blocked = false;
1298 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001299 if (send_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001300 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001302 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001303 free(cmd);
1304 }
1305
1306 pthread_cond_signal(&out->cond);
1307 while (!list_empty(&out->offload_cmd_list)) {
1308 item = list_head(&out->offload_cmd_list);
1309 list_remove(item);
1310 free(node_to_item(item, struct offload_cmd, node));
1311 }
1312 pthread_mutex_unlock(&out->lock);
1313
1314 return NULL;
1315}
1316
1317static int create_offload_callback_thread(struct stream_out *out)
1318{
1319 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1320 list_init(&out->offload_cmd_list);
1321 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1322 offload_thread_loop, out);
1323 return 0;
1324}
1325
1326static int destroy_offload_callback_thread(struct stream_out *out)
1327{
1328 pthread_mutex_lock(&out->lock);
1329 stop_compressed_output_l(out);
1330 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1331
1332 pthread_mutex_unlock(&out->lock);
1333 pthread_join(out->offload_thread, (void **) NULL);
1334 pthread_cond_destroy(&out->offload_cond);
1335
1336 return 0;
1337}
1338
Eric Laurent07eeafd2013-10-06 12:52:49 -07001339static bool allow_hdmi_channel_config(struct audio_device *adev)
1340{
1341 struct listnode *node;
1342 struct audio_usecase *usecase;
1343 bool ret = true;
1344
1345 list_for_each(node, &adev->usecase_list) {
1346 usecase = node_to_item(node, struct audio_usecase, list);
1347 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1348 /*
1349 * If voice call is already existing, do not proceed further to avoid
1350 * disabling/enabling both RX and TX devices, CSD calls, etc.
1351 * Once the voice call done, the HDMI channels can be configured to
1352 * max channels of remaining use cases.
1353 */
1354 if (usecase->id == USECASE_VOICE_CALL) {
1355 ALOGD("%s: voice call is active, no change in HDMI channels",
1356 __func__);
1357 ret = false;
1358 break;
1359 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1360 ALOGD("%s: multi channel playback is active, "
1361 "no change in HDMI channels", __func__);
1362 ret = false;
1363 break;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001364 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001365 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001366 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1367 ", no change in HDMI channels", __func__,
1368 usecase->stream.out->channel_mask);
Mingming Yin139f1072014-02-24 17:56:01 -08001369 ret = false;
1370 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001371 }
1372 }
1373 }
1374 return ret;
1375}
1376
1377static int check_and_set_hdmi_channels(struct audio_device *adev,
1378 unsigned int channels)
1379{
1380 struct listnode *node;
1381 struct audio_usecase *usecase;
1382
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001383 unsigned int supported_channels = platform_edid_get_max_channels(
1384 adev->platform);
1385 ALOGV("supported_channels %d, channels %d", supported_channels, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001386 /* Check if change in HDMI channel config is allowed */
1387 if (!allow_hdmi_channel_config(adev))
1388 return 0;
1389
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001390 if (channels > supported_channels)
1391 channels = supported_channels;
1392
Eric Laurent07eeafd2013-10-06 12:52:49 -07001393 if (channels == adev->cur_hdmi_channels) {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001394 ALOGD("%s: Requested channels are same as current channels(%d)",
1395 __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001396 return 0;
1397 }
1398
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001399 /*TODO: CHECK for passthrough don't set channel map for passthrough*/
Eric Laurent07eeafd2013-10-06 12:52:49 -07001400 platform_set_hdmi_channels(adev->platform, channels);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001401 platform_set_edid_channels_configuration(adev->platform, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001402 adev->cur_hdmi_channels = channels;
1403
1404 /*
1405 * Deroute all the playback streams routed to HDMI so that
1406 * the back end is deactivated. Note that backend will not
1407 * be deactivated if any one stream is connected to it.
1408 */
1409 list_for_each(node, &adev->usecase_list) {
1410 usecase = node_to_item(node, struct audio_usecase, list);
1411 if (usecase->type == PCM_PLAYBACK &&
1412 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001413 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001414 }
1415 }
1416
1417 /*
1418 * Enable all the streams disabled above. Now the HDMI backend
1419 * will be activated with new channel configuration
1420 */
1421 list_for_each(node, &adev->usecase_list) {
1422 usecase = node_to_item(node, struct audio_usecase, list);
1423 if (usecase->type == PCM_PLAYBACK &&
1424 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001425 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001426 }
1427 }
1428
1429 return 0;
1430}
1431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432static int stop_output_stream(struct stream_out *out)
1433{
1434 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435 struct audio_usecase *uc_info;
1436 struct audio_device *adev = out->dev;
1437
Eric Laurent994a6932013-07-17 11:51:42 -07001438 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001440 uc_info = get_usecase_from_list(adev, out->usecase);
1441 if (uc_info == NULL) {
1442 ALOGE("%s: Could not find the usecase (%d) in the list",
1443 __func__, out->usecase);
1444 return -EINVAL;
1445 }
1446
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001447 if (is_offload_usecase(out->usecase) &&
1448 !(audio_extn_dolby_is_passthrough_stream(out->flags))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001449 if (adev->visualizer_stop_output != NULL)
1450 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001451
1452 audio_extn_dts_remove_state_notifier_node(out->usecase);
1453
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001454 if (adev->offload_effects_stop_output != NULL)
1455 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1456 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001457
Eric Laurent150dbfe2013-02-27 14:31:02 -08001458 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001459 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001460
1461 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001462 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001464 list_remove(&uc_info->list);
1465 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001467 if (is_offload_usecase(out->usecase) &&
1468 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
1469 (audio_extn_dolby_is_passthrough_stream(out->flags))) {
1470 ALOGV("Disable passthrough , reset mixer to pcm");
1471 /* NO_PASSTHROUGH */
1472 out->compr_config.codec->compr_passthr = 0;
1473 audio_extn_dolby_set_hdmi_config(adev, out);
1474 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1475 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001476 /* Must be called after removing the usecase from list */
1477 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1478 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1479
Eric Laurent994a6932013-07-17 11:51:42 -07001480 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 return ret;
1482}
1483
1484int start_output_stream(struct stream_out *out)
1485{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 int ret = 0;
Mingming Yin9c041392014-05-01 15:37:31 -07001487 int sink_channels = 0;
1488 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 struct audio_usecase *uc_info;
1490 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301491 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001493 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1494 ret = -EINVAL;
1495 goto error_config;
1496 }
1497
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301498 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1499 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1500 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301501
Naresh Tanniru80659832014-06-04 18:17:56 +05301502 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301503 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301504 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301505 goto error_config;
1506 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301507
Eric Laurentb23d5282013-05-14 15:27:20 -07001508 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 if (out->pcm_device_id < 0) {
1510 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1511 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001512 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001513 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 }
1515
1516 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001517
1518 if (!uc_info) {
1519 ret = -ENOMEM;
1520 goto error_config;
1521 }
1522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 uc_info->id = out->usecase;
1524 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001525 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526 uc_info->devices = out->devices;
1527 uc_info->in_snd_device = SND_DEVICE_NONE;
1528 uc_info->out_snd_device = SND_DEVICE_NONE;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001529 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001530 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001531 if (is_offload_usecase(out->usecase)) {
1532 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001533 audio_extn_dolby_update_passt_stream_configuration(adev, out);
1534 }
1535 }
Mingming Yin9c041392014-05-01 15:37:31 -07001536 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1537 if (!strncmp("true", prop_value, 4)) {
1538 sink_channels = platform_edid_get_max_channels(out->dev->platform);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001539 ALOGD("%s: set HDMI channel count[%d] based on sink capability",
1540 __func__, sink_channels);
Mingming Yin9c041392014-05-01 15:37:31 -07001541 check_and_set_hdmi_channels(adev, sink_channels);
1542 } else {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001543 if (is_offload_usecase(out->usecase)) {
1544 unsigned int ch_count = out->compr_config.codec->ch_in;
1545 if (audio_extn_dolby_is_passthrough_stream(out->flags))
1546 /* backend channel config for passthrough stream is stereo */
1547 ch_count = 2;
1548 check_and_set_hdmi_channels(adev, ch_count);
1549 } else
Mingming Yin9c041392014-05-01 15:37:31 -07001550 check_and_set_hdmi_channels(adev, out->config.channels);
1551 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001552 audio_extn_dolby_set_hdmi_config(adev, out);
Mingming Yin10fef6a2013-11-26 17:17:01 -08001553 }
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001554 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 select_devices(adev, out->usecase);
1557
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001558 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1559 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001560 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001561 unsigned int flags = PCM_OUT;
1562 unsigned int pcm_open_retry_count = 0;
1563 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1564 flags |= PCM_MMAP | PCM_NOIRQ;
1565 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1566 } else
1567 flags |= PCM_MONOTONIC;
1568
1569 while (1) {
1570 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1571 flags, &out->config);
1572 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1573 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1574 if (out->pcm != NULL) {
1575 pcm_close(out->pcm);
1576 out->pcm = NULL;
1577 }
1578 if (pcm_open_retry_count-- == 0) {
1579 ret = -EIO;
1580 goto error_open;
1581 }
1582 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1583 continue;
1584 }
1585 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001587 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1588 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001590 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1591 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001593 out->compr = compress_open(adev->snd_card,
1594 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001595 COMPRESS_IN, &out->compr_config);
1596 if (out->compr && !is_compress_ready(out->compr)) {
1597 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1598 compress_close(out->compr);
1599 out->compr = NULL;
1600 ret = -EIO;
1601 goto error_open;
1602 }
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301603 /* compress_open sends params of the track, so reset the flag here */
1604 out->is_compr_metadata_avail = false;
1605
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001606 if (out->offload_callback)
1607 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001608
Fred Oh3f43e742015-03-04 18:42:34 -08001609 /* Since small bufs uses blocking writes, a write will be blocked
1610 for the default max poll time (20s) in the event of an SSR.
1611 Reduce the poll time to observe and deal with SSR faster.
1612 */
1613 if (out->use_small_bufs) {
1614 compress_set_max_poll_wait(out->compr, 1000);
1615 }
1616
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001617 audio_extn_dts_create_state_notifier_node(out->usecase);
1618 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1619 popcount(out->channel_mask),
1620 out->playback_started);
1621
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001622#ifdef DS1_DOLBY_DDP_ENABLED
1623 if (audio_extn_is_dolby_format(out->format))
1624 audio_extn_dolby_send_ddp_endp_params(adev);
1625#endif
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001626 if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) {
1627 if (adev->visualizer_start_output != NULL)
1628 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1629 if (adev->offload_effects_start_output != NULL)
1630 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001631 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 }
Eric Laurent994a6932013-07-17 11:51:42 -07001634 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001636error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001638error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001639 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640}
1641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642static int check_input_parameters(uint32_t sample_rate,
1643 audio_format_t format,
1644 int channel_count)
1645{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001646 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001648 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001649 !voice_extn_compress_voip_is_format_supported(format) &&
1650 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001651
1652 switch (channel_count) {
1653 case 1:
1654 case 2:
1655 case 6:
1656 break;
1657 default:
1658 ret = -EINVAL;
1659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660
1661 switch (sample_rate) {
1662 case 8000:
1663 case 11025:
1664 case 12000:
1665 case 16000:
1666 case 22050:
1667 case 24000:
1668 case 32000:
1669 case 44100:
1670 case 48000:
1671 break;
1672 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001673 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 }
1675
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001676 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677}
1678
1679static size_t get_input_buffer_size(uint32_t sample_rate,
1680 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001681 int channel_count,
1682 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683{
1684 size_t size = 0;
1685
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001686 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1687 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001688
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001689 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001690 if (is_low_latency)
1691 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001692 /* ToDo: should use frame_size computed based on the format and
1693 channel_count here. */
1694 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001696 /* make sure the size is multiple of 32 bytes
1697 * At 48 kHz mono 16-bit PCM:
1698 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1699 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1700 */
1701 size += 0x1f;
1702 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001703
1704 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705}
1706
1707static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1708{
1709 struct stream_out *out = (struct stream_out *)stream;
1710
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001711 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712}
1713
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001714static int out_set_sample_rate(struct audio_stream *stream __unused,
1715 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716{
1717 return -ENOSYS;
1718}
1719
1720static size_t out_get_buffer_size(const struct audio_stream *stream)
1721{
1722 struct stream_out *out = (struct stream_out *)stream;
1723
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001724 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001726 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1727 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001729 return out->config.period_size *
1730 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731}
1732
1733static uint32_t out_get_channels(const struct audio_stream *stream)
1734{
1735 struct stream_out *out = (struct stream_out *)stream;
1736
1737 return out->channel_mask;
1738}
1739
1740static audio_format_t out_get_format(const struct audio_stream *stream)
1741{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001742 struct stream_out *out = (struct stream_out *)stream;
1743
1744 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745}
1746
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001747static int out_set_format(struct audio_stream *stream __unused,
1748 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749{
1750 return -ENOSYS;
1751}
1752
1753static int out_standby(struct audio_stream *stream)
1754{
1755 struct stream_out *out = (struct stream_out *)stream;
1756 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301758 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1759 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001760 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1761 /* Ignore standby in case of voip call because the voip output
1762 * stream is closed in adev_close_output_stream()
1763 */
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301764 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001765 return 0;
1766 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001768 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001770 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 out->standby = true;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001772 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 if (out->pcm) {
1774 pcm_close(out->pcm);
1775 out->pcm = NULL;
1776 }
1777 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001778 ALOGD("copl(%p):standby", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 stop_compressed_output_l(out);
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05301780 out->send_next_track_params = false;
1781 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001782 out->gapless_mdata.encoder_delay = 0;
1783 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 if (out->compr != NULL) {
1785 compress_close(out->compr);
1786 out->compr = NULL;
1787 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001790 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 }
1792 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001793 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 return 0;
1795}
1796
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07001797static int out_dump(const struct audio_stream *stream __unused,
1798 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799{
1800 return 0;
1801}
1802
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001803static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1804{
1805 int ret = 0;
1806 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001807
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001808 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001809 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001810 return -EINVAL;
1811 }
1812
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001813 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1814 if (ret >= 0) {
1815 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1816 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1817 ALOGV("ADTS format is set in offload mode");
1818 }
ApurupaPattapu2e084df2013-12-18 15:47:59 -08001819 }
1820
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301821 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08001822
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001823 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1824 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301825 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001827 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1828 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05301829 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001830 }
1831
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001832 ALOGV("%s new encoder delay %u and padding %u", __func__,
1833 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1834
1835 return 0;
1836}
1837
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001838static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1839{
1840 return out == adev->primary_output || out == adev->voice_tx_output;
1841}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1844{
1845 struct stream_out *out = (struct stream_out *)stream;
1846 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001847 struct audio_usecase *usecase;
1848 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 struct str_parms *parms;
1850 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001851 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001852 bool select_new_device = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
sangwoobc677242013-08-08 16:53:43 +09001854 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301857 if (!parms)
1858 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001859 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1860 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001863 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001865 /*
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301866 * When HDMI cable is unplugged/usb hs is disconnected the
1867 * music playback is paused and the policy manager sends routing=0
1868 * But the audioflingercontinues to write data until standby time
1869 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001870 * Avoid this by routing audio to speaker until standby.
1871 */
Dhanalakshmi Siddani929a1f12014-04-18 22:26:56 +05301872 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
1873 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001874 val == AUDIO_DEVICE_NONE) {
Pradnya Chaphekard5349ce2014-11-05 11:40:26 -08001875 if (!audio_extn_dolby_is_passthrough_stream(out->flags))
1876 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001877 }
1878
1879 /*
1880 * select_devices() call below switches all the usecases on the same
1881 * backend to the new device. Refer to check_usecases_codec_backend() in
1882 * the select_devices(). But how do we undo this?
1883 *
1884 * For example, music playback is active on headset (deep-buffer usecase)
1885 * and if we go to ringtones and select a ringtone, low-latency usecase
1886 * will be started on headset+speaker. As we can't enable headset+speaker
1887 * and headset devices at the same time, select_devices() switches the music
1888 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1889 * So when the ringtone playback is completed, how do we undo the same?
1890 *
1891 * We are relying on the out_set_parameters() call on deep-buffer output,
1892 * once the ringtone playback is ended.
1893 * NOTE: We should not check if the current devices are same as new devices.
1894 * Because select_devices() must be called to switch back the music
1895 * playback to headset.
1896 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001897 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 out->devices = val;
1899
1900 if (!out->standby)
1901 select_devices(adev, out->usecase);
1902
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001903 if (output_drives_call(adev, out)) {
1904 if(!voice_is_in_call(adev)) {
1905 if (adev->mode == AUDIO_MODE_IN_CALL) {
1906 adev->current_call_output = out;
1907 ret = voice_start_call(adev);
1908 }
1909 } else {
1910 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001911 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07001912 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001913 }
1914 }
1915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001917 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001919
1920 if (out == adev->primary_output) {
1921 pthread_mutex_lock(&adev->lock);
1922 audio_extn_set_parameters(adev, parms);
1923 pthread_mutex_unlock(&adev->lock);
1924 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001925 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001926 pthread_mutex_lock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001927 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001928
1929 audio_extn_dts_create_state_notifier_node(out->usecase);
1930 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1931 popcount(out->channel_mask),
1932 out->playback_started);
1933
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001934 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001935 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301938error:
Eric Laurent994a6932013-07-17 11:51:42 -07001939 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940 return ret;
1941}
1942
1943static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1944{
1945 struct stream_out *out = (struct stream_out *)stream;
1946 struct str_parms *query = str_parms_create_str(keys);
1947 char *str;
1948 char value[256];
1949 struct str_parms *reply = str_parms_create();
1950 size_t i, j;
1951 int ret;
1952 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001953
1954 if (!query || !reply) {
1955 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1956 return NULL;
1957 }
1958
Eric Laurent994a6932013-07-17 11:51:42 -07001959 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1961 if (ret >= 0) {
1962 value[0] = '\0';
1963 i = 0;
1964 while (out->supported_channel_masks[i] != 0) {
1965 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1966 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1967 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001968 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001970 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971 first = false;
1972 break;
1973 }
1974 }
1975 i++;
1976 }
1977 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1978 str = str_parms_to_str(reply);
1979 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001980 voice_extn_out_get_parameters(out, query, reply);
1981 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08001982 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08001983 free(str);
1984 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001985 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001987
1988 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
1989 if (ret >= 0) {
1990 value[0] = '\0';
1991 i = 0;
1992 first = true;
1993 while (out->supported_formats[i] != 0) {
1994 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
1995 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
1996 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001997 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001998 }
1999 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2000 first = false;
2001 break;
2002 }
2003 }
2004 i++;
2005 }
2006 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
2007 str = str_parms_to_str(reply);
2008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009 str_parms_destroy(query);
2010 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002011 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 return str;
2013}
2014
2015static uint32_t out_get_latency(const struct audio_stream_out *stream)
2016{
2017 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002018 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019
Alexy Josephaa54c872014-12-03 02:46:47 -08002020 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002021 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Josephaa54c872014-12-03 02:46:47 -08002022 } else {
2023 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002025 }
2026
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302027 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002028 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029}
2030
2031static int out_set_volume(struct audio_stream_out *stream, float left,
2032 float right)
2033{
Eric Laurenta9024de2013-04-04 09:19:12 -07002034 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 int volume[2];
2036
Eric Laurenta9024de2013-04-04 09:19:12 -07002037 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2038 /* only take left channel into account: the API is for stereo anyway */
2039 out->muted = (left == 0.0f);
2040 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002041 } else if (is_offload_usecase(out->usecase)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002042 if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2043 /*
2044 * Set mute or umute on HDMI passthrough stream.
2045 * Only take left channel into account.
2046 * Mute is 0 and unmute 1
2047 */
2048 audio_extn_dolby_set_passt_volume(out, (left == 0.0f));
2049 } else {
2050 char mixer_ctl_name[128];
2051 struct audio_device *adev = out->dev;
2052 struct mixer_ctl *ctl;
2053 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002054 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002055
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002056 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2057 "Compress Playback %d Volume", pcm_device_id);
2058 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2059 if (!ctl) {
2060 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2061 __func__, mixer_ctl_name);
2062 return -EINVAL;
2063 }
2064 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2065 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2066 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2067 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002069 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 return -ENOSYS;
2072}
2073
2074static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2075 size_t bytes)
2076{
2077 struct stream_out *out = (struct stream_out *)stream;
2078 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302079 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002080 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 pthread_mutex_lock(&out->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302083
Naresh Tanniru80659832014-06-04 18:17:56 +05302084 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002085 // increase written size during SSR to avoid mismatch
2086 // with the written frames count in AF
2087 if (!is_offload_usecase(out->usecase))
2088 out->written += bytes / (out->config.channels * sizeof(short));
2089
Naresh Tanniru80659832014-06-04 18:17:56 +05302090 if (out->pcm) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302091 ALOGD(" %s: sound card is not active/SSR state", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302092 ret= -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302093 goto exit;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07002094 } else if (is_offload_usecase(out->usecase)) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302095 //during SSR for compress usecase we should return error to flinger
2096 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2097 pthread_mutex_unlock(&out->lock);
2098 return -ENETRESET;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302099 }
2100 }
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002103 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002104 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002105 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2106 ret = voice_extn_compress_voip_start_output_stream(out);
2107 else
2108 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002109 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002112 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 goto exit;
2114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116
Ashish Jain5a97ddd2015-05-13 10:52:34 +05302117 if (adev->mChannelStatusSet == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
2118 setChannelStatus(out, buffer, bytes);
2119 adev->mChannelStatusSet = true;
2120 }
2121
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002122 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002123 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002125 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2127 out->send_new_metadata = 0;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302128 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2129 ALOGD("copl(%p):send next track params in gapless", out);
2130 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2131 out->send_next_track_params = false;
2132 out->is_compr_metadata_avail = false;
2133 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002134 }
2135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302137 if (ret < 0)
2138 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002139 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002140 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302141 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302143 } else if (-ENETRESET == ret) {
2144 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2146 pthread_mutex_unlock(&out->lock);
2147 out_standby(&out->stream.common);
2148 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302150 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002152 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 out->playback_started = 1;
2154 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002155
2156 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2157 popcount(out->channel_mask),
2158 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 }
2160 pthread_mutex_unlock(&out->lock);
2161 return ret;
2162 } else {
2163 if (out->pcm) {
2164 if (out->muted)
2165 memset((void *)buffer, 0, bytes);
2166 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002167 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2168 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2169 else
2170 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302171 if (ret < 0)
2172 ret = -errno;
2173 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002174 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002176 }
2177
2178exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302179 /* ToDo: There may be a corner case when SSR happens back to back during
2180 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302181 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302182 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302183 }
2184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 pthread_mutex_unlock(&out->lock);
2186
2187 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002188 if (out->pcm)
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002189 ALOGE("%s: error %ld - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302190 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302191 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302192 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302193 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302194 out->standby = true;
2195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 out_standby(&out->stream.common);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002197 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302198 out_get_sample_rate(&out->stream.common));
2199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 }
2201 return bytes;
2202}
2203
2204static int out_get_render_position(const struct audio_stream_out *stream,
2205 uint32_t *dsp_frames)
2206{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302208 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002209
2210 if (dsp_frames == NULL)
2211 return -EINVAL;
2212
2213 *dsp_frames = 0;
2214 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002215 ssize_t ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002216 pthread_mutex_lock(&out->lock);
2217 if (out->compr != NULL) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302218 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302220 if (ret < 0)
2221 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 ALOGVV("%s rendered frames %d sample_rate %d",
2223 __func__, *dsp_frames, out->sample_rate);
2224 }
2225 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302226 if (-ENETRESET == ret) {
2227 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2228 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2229 return -EINVAL;
2230 } else if(ret < 0) {
2231 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2232 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302233 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2234 /*
2235 * Handle corner case where compress session is closed during SSR
2236 * and timestamp is queried
2237 */
2238 ALOGE(" ERROR: sound card not active, return error");
2239 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302240 } else {
2241 return 0;
2242 }
Zhou Song32a556e2015-05-05 10:46:56 +08002243 } else if (audio_is_linear_pcm(out->format)) {
2244 *dsp_frames = out->written;
2245 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 } else
2247 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248}
2249
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002250static int out_add_audio_effect(const struct audio_stream *stream __unused,
2251 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252{
2253 return 0;
2254}
2255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002256static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2257 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258{
2259 return 0;
2260}
2261
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002262static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2263 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264{
2265 return -EINVAL;
2266}
2267
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002268static int out_get_presentation_position(const struct audio_stream_out *stream,
2269 uint64_t *frames, struct timespec *timestamp)
2270{
2271 struct stream_out *out = (struct stream_out *)stream;
2272 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002273 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002274
2275 pthread_mutex_lock(&out->lock);
2276
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002277 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002278 if (out->compr != NULL) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302279 ret = compress_get_tstamp(out->compr, &dsp_frames,
Eric Laurent949a0892013-09-20 09:20:13 -07002280 &out->sample_rate);
2281 ALOGVV("%s rendered frames %ld sample_rate %d",
2282 __func__, dsp_frames, out->sample_rate);
2283 *frames = dsp_frames;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302284 if (ret < 0)
2285 ret = -errno;
2286 if (-ENETRESET == ret) {
2287 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2288 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2289 ret = -EINVAL;
2290 } else
2291 ret = 0;
2292
Eric Laurent949a0892013-09-20 09:20:13 -07002293 /* this is the best we can do */
2294 clock_gettime(CLOCK_MONOTONIC, timestamp);
2295 }
2296 } else {
2297 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002298 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002299 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2300 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002301 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002302 // This adjustment accounts for buffering after app processor.
2303 // It is based on estimated DSP latency per use case, rather than exact.
2304 signed_frames -=
2305 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2306
Eric Laurent949a0892013-09-20 09:20:13 -07002307 // It would be unusual for this value to be negative, but check just in case ...
2308 if (signed_frames >= 0) {
2309 *frames = signed_frames;
2310 ret = 0;
2311 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002312 }
2313 }
2314 }
2315
2316 pthread_mutex_unlock(&out->lock);
2317
2318 return ret;
2319}
2320
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002321static int out_set_callback(struct audio_stream_out *stream,
2322 stream_callback_t callback, void *cookie)
2323{
2324 struct stream_out *out = (struct stream_out *)stream;
2325
2326 ALOGV("%s", __func__);
2327 pthread_mutex_lock(&out->lock);
2328 out->offload_callback = callback;
2329 out->offload_cookie = cookie;
2330 pthread_mutex_unlock(&out->lock);
2331 return 0;
2332}
2333
2334static int out_pause(struct audio_stream_out* stream)
2335{
2336 struct stream_out *out = (struct stream_out *)stream;
2337 int status = -ENOSYS;
2338 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002339 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002340 ALOGD("copl(%p):pause compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 pthread_mutex_lock(&out->lock);
2342 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302343 struct audio_device *adev = out->dev;
2344 int snd_scard_state = get_snd_card_state(adev);
2345
2346 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2347 status = compress_pause(out->compr);
2348
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002349 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002350
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302351 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002352 audio_extn_dts_notify_playback_state(out->usecase, 0,
2353 out->sample_rate, popcount(out->channel_mask),
2354 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 }
2356 pthread_mutex_unlock(&out->lock);
2357 }
2358 return status;
2359}
2360
2361static int out_resume(struct audio_stream_out* stream)
2362{
2363 struct stream_out *out = (struct stream_out *)stream;
2364 int status = -ENOSYS;
2365 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002366 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002367 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 status = 0;
2369 pthread_mutex_lock(&out->lock);
2370 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302371 struct audio_device *adev = out->dev;
2372 int snd_scard_state = get_snd_card_state(adev);
2373
2374 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2375 status = compress_resume(out->compr);
2376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002378
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302379 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002380 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2381 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002382 }
2383 pthread_mutex_unlock(&out->lock);
2384 }
2385 return status;
2386}
2387
2388static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2389{
2390 struct stream_out *out = (struct stream_out *)stream;
2391 int status = -ENOSYS;
2392 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002393 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 pthread_mutex_lock(&out->lock);
2395 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2396 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2397 else
2398 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2399 pthread_mutex_unlock(&out->lock);
2400 }
2401 return status;
2402}
2403
2404static int out_flush(struct audio_stream_out* stream)
2405{
2406 struct stream_out *out = (struct stream_out *)stream;
2407 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002408 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002409 ALOGD("copl(%p):calling compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 pthread_mutex_lock(&out->lock);
2411 stop_compressed_output_l(out);
2412 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002413 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 return 0;
2415 }
2416 return -ENOSYS;
2417}
2418
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419/** audio_stream_in implementation **/
2420static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2421{
2422 struct stream_in *in = (struct stream_in *)stream;
2423
2424 return in->config.rate;
2425}
2426
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002427static int in_set_sample_rate(struct audio_stream *stream __unused,
2428 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429{
2430 return -ENOSYS;
2431}
2432
2433static size_t in_get_buffer_size(const struct audio_stream *stream)
2434{
2435 struct stream_in *in = (struct stream_in *)stream;
2436
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002437 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2438 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002439 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2440 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002441
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002442 return in->config.period_size *
2443 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444}
2445
2446static uint32_t in_get_channels(const struct audio_stream *stream)
2447{
2448 struct stream_in *in = (struct stream_in *)stream;
2449
2450 return in->channel_mask;
2451}
2452
2453static audio_format_t in_get_format(const struct audio_stream *stream)
2454{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002455 struct stream_in *in = (struct stream_in *)stream;
2456
2457 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458}
2459
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002460static int in_set_format(struct audio_stream *stream __unused,
2461 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462{
2463 return -ENOSYS;
2464}
2465
2466static int in_standby(struct audio_stream *stream)
2467{
2468 struct stream_in *in = (struct stream_in *)stream;
2469 struct audio_device *adev = in->dev;
2470 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302471 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2472 stream, in->usecase, use_case_table[in->usecase]);
2473
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002474 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2475 /* Ignore standby in case of voip call because the voip input
2476 * stream is closed in adev_close_input_stream()
2477 */
2478 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2479 return status;
2480 }
2481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482 pthread_mutex_lock(&in->lock);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002483 if (!in->standby && in->is_st_session) {
2484 ALOGD("%s: sound trigger pcm stop lab", __func__);
2485 audio_extn_sound_trigger_stop_lab(in);
2486 in->standby = 1;
2487 }
2488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002490 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002492 if (in->pcm) {
2493 pcm_close(in->pcm);
2494 in->pcm = NULL;
2495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002497 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 }
2499 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002500 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501 return status;
2502}
2503
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002504static int in_dump(const struct audio_stream *stream __unused,
2505 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506{
2507 return 0;
2508}
2509
2510static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2511{
2512 struct stream_in *in = (struct stream_in *)stream;
2513 struct audio_device *adev = in->dev;
2514 struct str_parms *parms;
2515 char *str;
2516 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002517 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302519 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 parms = str_parms_create_str(kvpairs);
2521
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302522 if (!parms)
2523 goto error;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002525 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002526
2527 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2528 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 val = atoi(value);
2530 /* no audio source uses val == 0 */
2531 if ((in->source != val) && (val != 0)) {
2532 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002533 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2534 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2535 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2536 (in->config.rate == 8000 || in->config.rate == 16000) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002537 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002538 err = voice_extn_compress_voip_open_input_stream(in);
2539 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002540 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08002541 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002542 }
2543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 }
2545 }
2546
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002547 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2548 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002550 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 in->device = val;
2552 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002553 if (!in->standby && !in->is_st_session)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002554 ret = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 }
2556 }
2557
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08002558done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002560 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561
2562 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302563error:
Eric Laurent994a6932013-07-17 11:51:42 -07002564 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 return ret;
2566}
2567
2568static char* in_get_parameters(const struct audio_stream *stream,
2569 const char *keys)
2570{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002571 struct stream_in *in = (struct stream_in *)stream;
2572 struct str_parms *query = str_parms_create_str(keys);
2573 char *str;
2574 char value[256];
2575 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002576
2577 if (!query || !reply) {
2578 ALOGE("in_get_parameters: failed to create query or reply");
2579 return NULL;
2580 }
2581
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002582 ALOGV("%s: enter: keys - %s", __func__, keys);
2583
2584 voice_extn_in_get_parameters(in, query, reply);
2585
2586 str = str_parms_to_str(reply);
2587 str_parms_destroy(query);
2588 str_parms_destroy(reply);
2589
2590 ALOGV("%s: exit: returns - %s", __func__, str);
2591 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592}
2593
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002594static int in_set_gain(struct audio_stream_in *stream __unused,
2595 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596{
2597 return 0;
2598}
2599
2600static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2601 size_t bytes)
2602{
2603 struct stream_in *in = (struct stream_in *)stream;
2604 struct audio_device *adev = in->dev;
2605 int i, ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05302606 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 pthread_mutex_lock(&in->lock);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302609
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002610 if (in->is_st_session) {
2611 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
2612 /* Read from sound trigger HAL */
2613 audio_extn_sound_trigger_read(in, buffer, bytes);
2614 pthread_mutex_unlock(&in->lock);
2615 return bytes;
2616 }
2617
2618 if (in->pcm && (SND_CARD_STATE_OFFLINE == snd_scard_state)) {
2619 ALOGD(" %s: sound card is not active/SSR state", __func__);
2620 ret= -EIO;;
2621 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302622 }
2623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 if (in->standby) {
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002625 pthread_mutex_lock(&adev->lock);
2626 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2627 ret = voice_extn_compress_voip_start_input_stream(in);
2628 else
2629 ret = start_input_stream(in);
2630 pthread_mutex_unlock(&adev->lock);
2631 if (ret != 0) {
2632 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 }
2634 in->standby = 0;
2635 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636
2637 if (in->pcm) {
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002638 if (audio_extn_ssr_get_enabled() &&
2639 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002640 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002641 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2642 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002643 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2644 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002645 else
2646 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302647 if (ret < 0)
2648 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 }
2650
2651 /*
2652 * Instead of writing zeroes here, we could trust the hardware
2653 * to always provide zeroes when muted.
2654 */
Pavan Chikkala63964842014-12-04 10:48:28 +05302655 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2656 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 memset(buffer, 0, bytes);
2658
2659exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302660 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302661 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07002662 if (-ENETRESET == ret)
2663 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 pthread_mutex_unlock(&in->lock);
2666
2667 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302668 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302669 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302670 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302671 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302672 in->standby = true;
2673 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302674 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07002676 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002677 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302678 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 }
2680 return bytes;
2681}
2682
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002683static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684{
2685 return 0;
2686}
2687
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002688static int add_remove_audio_effect(const struct audio_stream *stream,
2689 effect_handle_t effect,
2690 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002692 struct stream_in *in = (struct stream_in *)stream;
2693 int status = 0;
2694 effect_descriptor_t desc;
2695
2696 status = (*effect)->get_descriptor(effect, &desc);
2697 if (status != 0)
2698 return status;
2699
2700 pthread_mutex_lock(&in->lock);
2701 pthread_mutex_lock(&in->dev->lock);
2702 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2703 in->enable_aec != enable &&
2704 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2705 in->enable_aec = enable;
2706 if (!in->standby)
2707 select_devices(in->dev, in->usecase);
2708 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002709 if (in->enable_ns != enable &&
2710 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2711 in->enable_ns = enable;
2712 if (!in->standby)
2713 select_devices(in->dev, in->usecase);
2714 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002715 pthread_mutex_unlock(&in->dev->lock);
2716 pthread_mutex_unlock(&in->lock);
2717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 return 0;
2719}
2720
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002721static int in_add_audio_effect(const struct audio_stream *stream,
2722 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723{
Eric Laurent994a6932013-07-17 11:51:42 -07002724 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002725 return add_remove_audio_effect(stream, effect, true);
2726}
2727
2728static int in_remove_audio_effect(const struct audio_stream *stream,
2729 effect_handle_t effect)
2730{
Eric Laurent994a6932013-07-17 11:51:42 -07002731 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002732 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733}
2734
2735static int adev_open_output_stream(struct audio_hw_device *dev,
2736 audio_io_handle_t handle,
2737 audio_devices_t devices,
2738 audio_output_flags_t flags,
2739 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002740 struct audio_stream_out **stream_out,
2741 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742{
2743 struct audio_device *adev = (struct audio_device *)dev;
2744 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002745 int i, ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002746 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302749
2750 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2751 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2752 ALOGE(" sound card is not active rejecting compress output open request");
2753 return -EINVAL;
2754 }
2755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2757
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302758 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2759 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2760 devices, flags, &out->stream);
2761
2762
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002763 if (!out) {
2764 return -ENOMEM;
2765 }
2766
Haynes Mathew George204045b2015-02-25 20:32:03 -08002767 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2768 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770 if (devices == AUDIO_DEVICE_NONE)
2771 devices = AUDIO_DEVICE_OUT_SPEAKER;
2772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 out->flags = flags;
2774 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002775 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002776 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777 out->sample_rate = config->sample_rate;
2778 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2779 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002780 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002781 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08002782 out->non_blocking = 0;
2783 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 /* Init use case and pcm_config */
Mingming Yin2264ad32015-07-21 15:22:22 -07002785 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2786 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002787 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
2788 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
2789
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002790 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002791 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2792 ret = read_hdmi_channel_masks(out);
2793
2794 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2795 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002796 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002797 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002798 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799
2800 if (config->sample_rate == 0)
2801 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2802 if (config->channel_mask == 0)
2803 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2804
2805 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2808 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002810 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002812 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2813 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002814 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002815 ret = voice_extn_compress_voip_open_output_stream(out);
2816 if (ret != 0) {
2817 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2818 __func__, ret);
2819 goto error_open;
2820 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2822 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2823 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2824 ALOGE("%s: Unsupported Offload information", __func__);
2825 ret = -EINVAL;
2826 goto error_open;
2827 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002828
2829 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2830 ((audio_extn_dolby_is_passthrough_stream(out->flags)))) {
2831 ALOGV("read and update_pass through formats");
2832 ret = audio_extn_dolby_update_passt_formats(adev, out);
2833 if(ret != 0) {
2834 goto error_open;
2835 }
2836 if(config->offload_info.format == 0)
2837 config->offload_info.format = out->supported_formats[0];
2838 }
2839
Mingming Yin90310102013-11-13 16:57:00 -08002840 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002841 !audio_extn_is_dolby_format(config->offload_info.format)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 ALOGE("%s: Unsupported audio format", __func__);
2843 ret = -EINVAL;
2844 goto error_open;
2845 }
2846
2847 out->compr_config.codec = (struct snd_codec *)
2848 calloc(1, sizeof(struct snd_codec));
2849
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002850 if (!out->compr_config.codec) {
2851 ret = -ENOMEM;
2852 goto error_open;
2853 }
2854
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002855 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 if (config->offload_info.channel_mask)
2857 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002858 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002860 config->offload_info.channel_mask = config->channel_mask;
2861 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002862 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 out->sample_rate = config->offload_info.sample_rate;
2864
2865 out->stream.set_callback = out_set_callback;
2866 out->stream.pause = out_pause;
2867 out->stream.resume = out_resume;
2868 out->stream.drain = out_drain;
2869 out->stream.flush = out_flush;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002870 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002872 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002873 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002874 audio_extn_dolby_get_snd_codec_id(adev, out,
2875 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002876 else
2877 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 get_snd_codec_id(config->offload_info.format);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002879 if (audio_is_offload_pcm(config->offload_info.format)) {
2880 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002881 platform_get_pcm_offload_buffer_size(&config->offload_info);
2882 } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) {
2883 out->compr_config.fragment_size =
2884 audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002885 } else {
2886 out->compr_config.fragment_size =
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002887 platform_get_compress_offload_buffer_size(&config->offload_info);
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002888 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2890 out->compr_config.codec->sample_rate =
Ravi Kumar Alamanda433dfe02014-11-14 12:05:54 -08002891 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->compr_config.codec->bit_rate =
2893 config->offload_info.bit_rate;
2894 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002895 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002897 out->bit_width = PCM_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002898 /*TODO: Do we need to change it for passthrough */
2899 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900
Mingming Yin3ee55c62014-08-04 14:23:35 -07002901 if (config->offload_info.format == AUDIO_FORMAT_AAC)
2902 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002903 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2904 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002905 if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08002906 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2907
Mingming Yin3ee55c62014-08-04 14:23:35 -07002908 if (out->bit_width == 24) {
2909 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
2910 }
2911
Amit Shekhar6f461b12014-08-01 14:52:58 -07002912 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Mingming Yinc9efb4f2014-09-19 12:16:36 -07002913 out->compr_config.codec->options.flac_dec.sample_size = PCM_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07002914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2916 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002917
Alexy Josephaa54c872014-12-03 02:46:47 -08002918 if (config->offload_info.use_small_bufs) {
2919 //this flag is set from framework only if its for PCM formats
2920 //no need to check for PCM format again
2921 out->non_blocking = 0;
2922 out->use_small_bufs = true;
2923 ALOGI("Keep write blocking for small buff: non_blockling %d",
2924 out->non_blocking);
2925 }
2926
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002927 out->send_new_metadata = 1;
Chaithanya Krishna Bacharaju74b06ea2015-07-24 14:15:05 +05302928 out->send_next_track_params = false;
2929 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002930 out->offload_state = OFFLOAD_STATE_IDLE;
2931 out->playback_started = 0;
2932
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002933 audio_extn_dts_create_state_notifier_node(out->usecase);
2934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 create_offload_callback_thread(out);
2936 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2937 __func__, config->offload_info.version,
2938 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002939 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -08002940 check_and_set_gapless_mode(adev);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002941 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2942 ret = voice_check_and_set_incall_music_usecase(adev, out);
2943 if (ret != 0) {
2944 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2945 __func__, ret);
2946 goto error_open;
2947 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002948 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2949 if (config->sample_rate == 0)
2950 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2951 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2952 config->sample_rate != 8000) {
2953 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2954 ret = -EINVAL;
2955 goto error_open;
2956 }
2957 out->sample_rate = config->sample_rate;
2958 out->config.rate = config->sample_rate;
2959 if (config->format == AUDIO_FORMAT_DEFAULT)
2960 config->format = AUDIO_FORMAT_PCM_16_BIT;
2961 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2962 config->format = AUDIO_FORMAT_PCM_16_BIT;
2963 ret = -EINVAL;
2964 goto error_open;
2965 }
2966 out->format = config->format;
2967 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2968 out->config = pcm_config_afe_proxy_playback;
2969 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002970 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002971 format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2973 out->config = pcm_config_low_latency;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002974 out->sample_rate = out->config.rate;
Mingming Yin08c7e312015-03-16 18:10:58 -07002975 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2976 format = AUDIO_FORMAT_PCM_16_BIT;
2977 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2978 out->config = pcm_config_deep_buffer;
2979 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002980 } else {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002981 /* primary path is the default path selected if no other outputs are available/suitable */
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002982 format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002983 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Mingming Yin08c7e312015-03-16 18:10:58 -07002984 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002985 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 }
2987
Amit Shekhar1d896042014-10-03 13:16:09 -07002988 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2989 __func__, devices, flags, format, out->sample_rate, out->bit_width);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002990 /* TODO remove this hardcoding and check why width is zero*/
2991 if (out->bit_width == 0)
2992 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07002993 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
2994 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07002995 devices, flags, format, out->sample_rate,
Sidipotu Ashokc7a10c12015-06-17 09:49:34 +05302996 out->bit_width, &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002997 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
2998 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
2999 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003000 if(adev->primary_output == NULL)
3001 adev->primary_output = out;
3002 else {
3003 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003004 ret = -EEXIST;
3005 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003006 }
3007 }
3008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 /* Check if this usecase is already existing */
3010 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003011 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3012 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003015 ret = -EEXIST;
3016 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 }
3018 pthread_mutex_unlock(&adev->lock);
3019
3020 out->stream.common.get_sample_rate = out_get_sample_rate;
3021 out->stream.common.set_sample_rate = out_set_sample_rate;
3022 out->stream.common.get_buffer_size = out_get_buffer_size;
3023 out->stream.common.get_channels = out_get_channels;
3024 out->stream.common.get_format = out_get_format;
3025 out->stream.common.set_format = out_set_format;
3026 out->stream.common.standby = out_standby;
3027 out->stream.common.dump = out_dump;
3028 out->stream.common.set_parameters = out_set_parameters;
3029 out->stream.common.get_parameters = out_get_parameters;
3030 out->stream.common.add_audio_effect = out_add_audio_effect;
3031 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3032 out->stream.get_latency = out_get_latency;
3033 out->stream.set_volume = out_set_volume;
3034 out->stream.write = out_write;
3035 out->stream.get_render_position = out_get_render_position;
3036 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003037 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003040 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003041 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042
3043 config->format = out->stream.common.get_format(&out->stream.common);
3044 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3045 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3046
3047 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303048 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3049 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003050
3051 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3052 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3053 popcount(out->channel_mask), out->playback_started);
3054
Eric Laurent994a6932013-07-17 11:51:42 -07003055 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003057
3058error_open:
3059 free(out);
3060 *stream_out = NULL;
3061 ALOGD("%s: exit: ret %d", __func__, ret);
3062 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063}
3064
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003065static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 struct audio_stream_out *stream)
3067{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 struct stream_out *out = (struct stream_out *)stream;
3069 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003070 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303072 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003074 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303075 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003076 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303077 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 if(ret != 0)
3079 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3080 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003081 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003082 out_standby(&stream->common);
3083
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003084 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003085 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003087 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 if (out->compr_config.codec != NULL)
3089 free(out->compr_config.codec);
3090 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003091
3092 if (adev->voice_tx_output == out)
3093 adev->voice_tx_output = NULL;
3094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 pthread_cond_destroy(&out->cond);
3096 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003098 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099}
3100
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003101static void close_compress_sessions(struct audio_device *adev)
3102{
Mingming Yin7b762e72015-03-04 13:47:32 -08003103 struct stream_out *out;
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303104 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003105 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003106 pthread_mutex_lock(&adev->lock);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303107
3108 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003109 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303110 if (is_offload_usecase(usecase->id)) {
3111 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003112 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3113 out = usecase->stream.out;
3114 pthread_mutex_unlock(&adev->lock);
3115 out_standby(&out->stream.common);
3116 pthread_mutex_lock(&adev->lock);
3117 }
Naresh Tanniru85f301c2015-06-03 01:50:57 +05303118 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003119 }
3120 pthread_mutex_unlock(&adev->lock);
3121}
3122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3124{
3125 struct audio_device *adev = (struct audio_device *)dev;
3126 struct str_parms *parms;
3127 char *str;
3128 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003129 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003130 int ret;
3131 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003133 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303136 if (!parms)
3137 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003138 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3139 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303140 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303141 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303142 struct listnode *node;
3143 struct audio_usecase *usecase;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303144 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003146 //close compress sessions on OFFLINE status
3147 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303148 } else if (strstr(snd_card_status, "ONLINE")) {
3149 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303150 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Ramjee Singheb9127a2015-06-09 15:18:42 +05303151 if (!platform_is_acdb_initialized(adev->platform)) {
3152 ret = platform_acdb_init(adev->platform);
3153 if(ret)
3154 ALOGE("acdb initialization is failed");
3155
3156 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303157 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303158 }
3159
3160 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003161 status = voice_set_parameters(adev, parms);
3162 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003163 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003165 status = platform_set_parameters(adev->platform, parms);
3166 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003167 goto done;
3168
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3170 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003171 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3173 adev->bluetooth_nrec = true;
3174 else
3175 adev->bluetooth_nrec = false;
3176 }
3177
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003178 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3179 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3181 adev->screen_off = false;
3182 else
3183 adev->screen_off = true;
3184 }
3185
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003186 ret = str_parms_get_int(parms, "rotation", &val);
3187 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003188 bool reverse_speakers = false;
3189 switch(val) {
3190 // FIXME: note that the code below assumes that the speakers are in the correct placement
3191 // relative to the user when the device is rotated 90deg from its default rotation. This
3192 // assumption is device-specific, not platform-specific like this code.
3193 case 270:
3194 reverse_speakers = true;
3195 break;
3196 case 0:
3197 case 90:
3198 case 180:
3199 break;
3200 default:
3201 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003202 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003203 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003204 if (status == 0) {
3205 if (adev->speaker_lr_swap != reverse_speakers) {
3206 adev->speaker_lr_swap = reverse_speakers;
3207 // only update the selected device if there is active pcm playback
3208 struct audio_usecase *usecase;
3209 struct listnode *node;
3210 list_for_each(node, &adev->usecase_list) {
3211 usecase = node_to_item(node, struct audio_usecase, list);
3212 if (usecase->type == PCM_PLAYBACK) {
3213 select_devices(adev, usecase->id);
3214 break;
3215 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003216 }
3217 }
3218 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003219 }
3220
Mingming Yin514a8bc2014-07-29 15:22:21 -07003221 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3222 if (ret >= 0) {
3223 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3224 adev->bt_wb_speech_enabled = true;
3225 else
3226 adev->bt_wb_speech_enabled = false;
3227 }
3228
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003229 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3230 if (ret >= 0) {
3231 val = atoi(value);
3232 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3233 ALOGV("cache new edid");
3234 platform_cache_edid(adev->platform);
3235 }
3236 }
3237
3238 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3239 if (ret >= 0) {
3240 val = atoi(value);
3241 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3242 ALOGV("invalidate cached edid");
3243 platform_invalidate_edid(adev->platform);
3244 }
3245 }
3246
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003247 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003248
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003249done:
3250 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003251 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303252error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003253 ALOGV("%s: exit with code(%d)", __func__, status);
3254 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255}
3256
3257static char* adev_get_parameters(const struct audio_hw_device *dev,
3258 const char *keys)
3259{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003260 struct audio_device *adev = (struct audio_device *)dev;
3261 struct str_parms *reply = str_parms_create();
3262 struct str_parms *query = str_parms_create_str(keys);
3263 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05303264 char value[256] = {0};
3265 int ret = 0;
3266
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003267 if (!query || !reply) {
3268 ALOGE("adev_get_parameters: failed to create query or reply");
3269 return NULL;
3270 }
3271
Naresh Tannirud7205b62014-06-20 02:54:48 +05303272 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
3273 sizeof(value));
3274 if (ret >=0) {
3275 int val = 1;
3276 pthread_mutex_lock(&adev->snd_card_status.lock);
3277 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3278 val = 0;
3279 pthread_mutex_unlock(&adev->snd_card_status.lock);
3280 str_parms_add_int(reply, "SND_CARD_STATUS", val);
3281 goto exit;
3282 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003283
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003284 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003285 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003286 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003287 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05303288 pthread_mutex_unlock(&adev->lock);
3289
Naresh Tannirud7205b62014-06-20 02:54:48 +05303290exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003291 str = str_parms_to_str(reply);
3292 str_parms_destroy(query);
3293 str_parms_destroy(reply);
3294
3295 ALOGV("%s: exit: returns - %s", __func__, str);
3296 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297}
3298
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003299static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300{
3301 return 0;
3302}
3303
3304static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3305{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003306 int ret;
3307 struct audio_device *adev = (struct audio_device *)dev;
3308 pthread_mutex_lock(&adev->lock);
3309 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003310 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003311 pthread_mutex_unlock(&adev->lock);
3312 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313}
3314
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003315static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3316 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317{
3318 return -ENOSYS;
3319}
3320
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003321static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3322 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323{
3324 return -ENOSYS;
3325}
3326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003327static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3328 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329{
3330 return -ENOSYS;
3331}
3332
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003333static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3334 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335{
3336 return -ENOSYS;
3337}
3338
3339static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3340{
3341 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 pthread_mutex_lock(&adev->lock);
3344 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003345 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 adev->mode = mode;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003347 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3348 voice_is_in_call(adev)) {
3349 voice_stop_call(adev);
3350 adev->current_call_output = NULL;
3351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 }
3353 pthread_mutex_unlock(&adev->lock);
3354 return 0;
3355}
3356
3357static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3358{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003359 int ret;
3360
3361 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003362 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003363 ret = voice_set_mic_mute((struct audio_device *)dev, state);
3364 pthread_mutex_unlock(&adev->lock);
3365
3366 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367}
3368
3369static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3370{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003371 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 return 0;
3373}
3374
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003375static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 const struct audio_config *config)
3377{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003378 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003380 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3381 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382}
3383
3384static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthye3cce412015-04-27 15:47:55 -07003385 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 audio_devices_t devices,
3387 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003388 struct audio_stream_in **stream_in,
3389 audio_input_flags_t flags __unused,
3390 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003391 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392{
3393 struct audio_device *adev = (struct audio_device *)dev;
3394 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003395 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003396 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003397 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 *stream_in = NULL;
3400 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3401 return -EINVAL;
3402
3403 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003404
3405 if (!in) {
3406 ALOGE("failed to allocate input stream");
3407 return -ENOMEM;
3408 }
3409
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303410 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003411 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3412 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003414 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 in->stream.common.get_sample_rate = in_get_sample_rate;
3417 in->stream.common.set_sample_rate = in_set_sample_rate;
3418 in->stream.common.get_buffer_size = in_get_buffer_size;
3419 in->stream.common.get_channels = in_get_channels;
3420 in->stream.common.get_format = in_get_format;
3421 in->stream.common.set_format = in_set_format;
3422 in->stream.common.standby = in_standby;
3423 in->stream.common.dump = in_dump;
3424 in->stream.common.set_parameters = in_set_parameters;
3425 in->stream.common.get_parameters = in_get_parameters;
3426 in->stream.common.add_audio_effect = in_add_audio_effect;
3427 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3428 in->stream.set_gain = in_set_gain;
3429 in->stream.read = in_read;
3430 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3431
3432 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003433 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 in->standby = 1;
3436 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003437 in->capture_handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438
3439 /* Update config params with the requested sample rate and channels */
3440 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003441 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3442 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3443 is_low_latency = true;
3444#if LOW_LATENCY_CAPTURE_USE_CASE
3445 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3446#endif
3447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003450 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003452 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05303453 if (adev->mode != AUDIO_MODE_IN_CALL) {
3454 ret = -EINVAL;
3455 goto err_open;
3456 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003457 if (config->sample_rate == 0)
3458 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3459 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3460 config->sample_rate != 8000) {
3461 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3462 ret = -EINVAL;
3463 goto err_open;
3464 }
3465 if (config->format == AUDIO_FORMAT_DEFAULT)
3466 config->format = AUDIO_FORMAT_PCM_16_BIT;
3467 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3468 config->format = AUDIO_FORMAT_PCM_16_BIT;
3469 ret = -EINVAL;
3470 goto err_open;
3471 }
3472
3473 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3474 in->config = pcm_config_afe_proxy_record;
3475 in->config.channels = channel_count;
3476 in->config.rate = config->sample_rate;
3477 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003478 if(audio_extn_ssr_get_enabled()) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003479 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003480 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3481 ret = -EINVAL;
3482 goto err_open;
3483 }
3484 } else {
Mingming Yin3cf99da2014-09-16 17:41:33 -07003485 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003486 }
Mingming Yine62d7842013-10-25 16:26:03 -07003487 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003488 audio_extn_compr_cap_format_supported(config->format) &&
3489 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003490 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003491 } else {
3492 in->config.channels = channel_count;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003493 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003494 buffer_size = get_input_buffer_size(config->sample_rate,
3495 config->format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003496 channel_count,
3497 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003498 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07003499 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3500 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3501 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3502 (in->config.rate == 8000 || in->config.rate == 16000) &&
3503 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3504 voice_extn_compress_voip_open_input_stream(in);
3505 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003506 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003508 /* This stream could be for sound trigger lab,
3509 get sound trigger pcm if present */
3510 audio_extn_sound_trigger_check_and_get_session(in);
Sudheer Papothi390bcf32014-12-04 01:25:17 +05303511 audio_extn_perf_lock_init();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003512
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003514 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003515 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516
3517err_open:
3518 free(in);
3519 *stream_in = NULL;
3520 return ret;
3521}
3522
3523static void adev_close_input_stream(struct audio_hw_device *dev,
3524 struct audio_stream_in *stream)
3525{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003526 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003527 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003528 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303529
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303530 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003531
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05303532 /* Disable echo reference while closing input stream */
3533 platform_set_echo_reference(adev->platform, false);
3534
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003535 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303536 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003537 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303538 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003539 if (ret != 0)
3540 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3541 __func__, ret);
3542 } else
3543 in_standby(&stream->common);
3544
Mingming Yin7b762e72015-03-04 13:47:32 -08003545 if (audio_extn_ssr_get_enabled() &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003546 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003547 audio_extn_ssr_deinit();
3548 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549
Mingming Yine62d7842013-10-25 16:26:03 -07003550 if(audio_extn_compr_cap_enabled() &&
3551 audio_extn_compr_cap_format_supported(in->config.format))
3552 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003553
3554 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 return;
3556}
3557
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003558static int adev_dump(const audio_hw_device_t *device __unused,
3559 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560{
3561 return 0;
3562}
3563
3564static int adev_close(hw_device_t *device)
3565{
3566 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003567
3568 if (!adev)
3569 return 0;
3570
3571 pthread_mutex_lock(&adev_init_lock);
3572
3573 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003574 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08003575 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003576 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07003577 audio_route_free(adev->audio_route);
3578 free(adev->snd_dev_ref_cnt);
3579 platform_deinit(adev->platform);
Kiran Kandi910e1862013-10-29 13:29:42 -07003580 free(device);
3581 adev = NULL;
3582 }
3583 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003584 return 0;
3585}
3586
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003587/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3588 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3589 * just that it _might_ work.
3590 */
3591static int period_size_is_plausible_for_low_latency(int period_size)
3592{
3593 switch (period_size) {
3594 case 160:
3595 case 240:
3596 case 320:
3597 case 480:
3598 return 1;
3599 default:
3600 return 0;
3601 }
3602}
3603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003604static int adev_open(const hw_module_t *module, const char *name,
3605 hw_device_t **device)
3606{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003607 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003609 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3611
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003612 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003613 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003614 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003615 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003616 ALOGD("%s: returning existing instance of adev", __func__);
3617 ALOGD("%s: exit", __func__);
3618 pthread_mutex_unlock(&adev_init_lock);
3619 return 0;
3620 }
3621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 adev = calloc(1, sizeof(struct audio_device));
3623
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003624 if (!adev) {
3625 pthread_mutex_unlock(&adev_init_lock);
3626 return -ENOMEM;
3627 }
3628
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07003629 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3632 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3633 adev->device.common.module = (struct hw_module_t *)module;
3634 adev->device.common.close = adev_close;
3635
3636 adev->device.init_check = adev_init_check;
3637 adev->device.set_voice_volume = adev_set_voice_volume;
3638 adev->device.set_master_volume = adev_set_master_volume;
3639 adev->device.get_master_volume = adev_get_master_volume;
3640 adev->device.set_master_mute = adev_set_master_mute;
3641 adev->device.get_master_mute = adev_get_master_mute;
3642 adev->device.set_mode = adev_set_mode;
3643 adev->device.set_mic_mute = adev_set_mic_mute;
3644 adev->device.get_mic_mute = adev_get_mic_mute;
3645 adev->device.set_parameters = adev_set_parameters;
3646 adev->device.get_parameters = adev_get_parameters;
3647 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3648 adev->device.open_output_stream = adev_open_output_stream;
3649 adev->device.close_output_stream = adev_close_output_stream;
3650 adev->device.open_input_stream = adev_open_input_stream;
3651 adev->device.close_input_stream = adev_close_input_stream;
3652 adev->device.dump = adev_dump;
3653
3654 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003656 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003657 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003660 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003661 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003662 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003663 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003664 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08003665 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003666 adev->offload_usecases_state = 0;
Ashish Jain5a97ddd2015-05-13 10:52:34 +05303667 adev->mChannelStatusSet = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303668
3669 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3670 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003672 adev->platform = platform_init(adev);
3673 if (!adev->platform) {
3674 free(adev->snd_dev_ref_cnt);
3675 free(adev);
3676 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3677 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003678 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003679 return -EINVAL;
3680 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003681
Naresh Tanniru4c630392014-05-12 01:05:52 +05303682 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
3683
Eric Laurentc4aef752013-09-12 17:45:53 -07003684 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3685 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3686 if (adev->visualizer_lib == NULL) {
3687 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3688 } else {
3689 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3690 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003691 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003692 "visualizer_hal_start_output");
3693 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003694 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003695 "visualizer_hal_stop_output");
3696 }
3697 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003698 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003699 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07003700
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003701 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3702 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3703 if (adev->offload_effects_lib == NULL) {
3704 ALOGE("%s: DLOPEN failed for %s", __func__,
3705 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3706 } else {
3707 ALOGV("%s: DLOPEN successful for %s", __func__,
3708 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3709 adev->offload_effects_start_output =
3710 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3711 "offload_effects_bundle_hal_start_output");
3712 adev->offload_effects_stop_output =
3713 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3714 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003715 adev->offload_effects_set_hpx_state =
3716 (int (*)(bool))dlsym(adev->offload_effects_lib,
3717 "offload_effects_bundle_set_hpx_state");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003718 }
3719 }
3720
Mingming Yin514a8bc2014-07-29 15:22:21 -07003721 adev->bt_wb_speech_enabled = false;
3722
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07003723 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 *device = &adev->device.common;
3725
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003726 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
3727 &adev->streams_output_cfg_list);
3728
Kiran Kandi910e1862013-10-29 13:29:42 -07003729 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003730
3731 char value[PROPERTY_VALUE_MAX];
3732 int trial;
3733 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3734 trial = atoi(value);
3735 if (period_size_is_plausible_for_low_latency(trial)) {
3736 pcm_config_low_latency.period_size = trial;
3737 pcm_config_low_latency.start_threshold = trial / 4;
3738 pcm_config_low_latency.avail_min = trial / 4;
3739 configured_low_latency_capture_period_size = trial;
3740 }
3741 }
3742 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3743 trial = atoi(value);
3744 if (period_size_is_plausible_for_low_latency(trial)) {
3745 configured_low_latency_capture_period_size = trial;
3746 }
3747 }
3748
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003749 pthread_mutex_unlock(&adev_init_lock);
3750
Eric Laurent994a6932013-07-17 11:51:42 -07003751 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752 return 0;
3753}
3754
3755static struct hw_module_methods_t hal_module_methods = {
3756 .open = adev_open,
3757};
3758
3759struct audio_module HAL_MODULE_INFO_SYM = {
3760 .common = {
3761 .tag = HARDWARE_MODULE_TAG,
3762 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3763 .hal_api_version = HARDWARE_HAL_API_VERSION,
3764 .id = AUDIO_HARDWARE_MODULE_ID,
3765 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003766 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 .methods = &hal_module_methods,
3768 },
3769};